# HG changeset patch # User Bradley M. Kuhn # Date 2014-07-03 01:08:45 # Node ID 3777939c8674f07cbb52f88598937aa4756fd255 # Parent 18e4ecdb18476956323f2e0e5c7de15c4d4acc64 # Parent 1a035ab6e0820bb56cf69fa4945906dde3e6d19c Merge liberated and rebranded branches to default diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -18,10 +18,9 @@ syntax: regexp ^\.project$ ^\.pydevproject$ ^\.coverage$ -^rhodecode\.db$ +^kallithea\.db$ ^test\.db$ -^RhodeCode\.egg-info$ +^Kallithea\.egg-info$ ^rc.*\.ini$ ^fabfile.py -^\.rhodecode$ ^\.idea$ diff --git a/.travis.yml b/.travis.yml --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,9 @@ python: - "2.7" env: - - TEST_DB=sqlite:////tmp/rhodecode_test.sqlite - - TEST_DB=mysql://root@127.0.0.1/rhodecode_test - - TEST_DB=postgresql://postgres@127.0.0.1/rhodecode_test + - TEST_DB=sqlite:////tmp/kallithea_test.sqlite + - TEST_DB=mysql://root@127.0.0.1/kallithea_test + - TEST_DB=postgresql://postgres@127.0.0.1/kallithea_test services: - mysql @@ -15,8 +15,8 @@ services: # command to install dependencies before_script: - - mysql -e 'create database rhodecode_test;' - - psql -c 'create database rhodecode_test;' -U postgres + - mysql -e 'create database kallithea_test;' + - psql -c 'create database kallithea_test;' -U postgres - git --version before_install: @@ -34,8 +34,8 @@ script: nosetests notifications: email: - - marcinkuz@gmail.com - irc: "irc.freenode.org#rhodecode" + - ci@kallithea-scm.org + irc: "irc.freenode.org#kallithea" branches: only: diff --git a/.tx/config b/.tx/config --- a/.tx/config +++ b/.tx/config @@ -1,15 +1,16 @@ [main] host = https://www.transifex.com -[RhodeCode.pot] -source_file = rhodecode/i18n/rhodecode.pot +[Kallithea.pot] +source_file = kallithea/i18n/kallithea.pot source_lang = en -trans.pl = rhodecode/i18n/pl/LC_MESSAGES/rhodecode.po -trans.ru = rhodecode/i18n/ru/LC_MESSAGES/rhodecode.po -trans.fr = rhodecode/i18n/fr/LC_MESSAGES/rhodecode.po -trans.ja = rhodecode/i18n/ja/LC_MESSAGES/rhodecode.po -trans.pt_BR = rhodecode/i18n/pt_BR/LC_MESSAGES/rhodecode.po -trans.zh_CN = rhodecode/i18n/zh_CN/LC_MESSAGES/rhodecode.po -trans.zh_TW = rhodecode/i18n/zh_TW/LC_MESSAGES/rhodecode.po +trans.pl = kallithea/i18n/pl/LC_MESSAGES/kallithea.po +trans.ru = kallithea/i18n/ru/LC_MESSAGES/kallithea.po +trans.fr = kallithea/i18n/fr/LC_MESSAGES/kallithea.po +trans.ja = kallithea/i18n/ja/LC_MESSAGES/kallithea.po +trans.pt_BR = kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po +trans.zh_CN = kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po +trans.zh_TW = kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po +trans.de = kallithea/i18n/de/LC_MESSAGES/kallithea.po type = PO diff --git a/Apache-License-2.0.txt b/Apache-License-2.0.txt new file mode 100644 --- /dev/null +++ b/Apache-License-2.0.txt @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/CONTRIBUTORS b/CONTRIBUTORS --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,4 +1,4 @@ -List of contributors to RhodeCode project: +List of contributors to Kallithea project: Marcin Kuźmiński Lukasz Balcerzak Jason Harris @@ -37,4 +37,11 @@ List of contributors to RhodeCode projec Simon Lopez Jonathan Sternberg Grzegorz Rożniecki - + Andrew Kesterson + David A. Sjøen + Jelmer Vernooij + larikale + SteveCohen + Kallithea GmbH + Sebastian Kreutzberger + thomas diff --git a/LICENSE-MERGELY.html b/LICENSE-MERGELY.html new file mode 100644 --- /dev/null +++ b/LICENSE-MERGELY.html @@ -0,0 +1,111 @@ + + + + + Mergely License + + + + + + + + + + + + + + +
+
+ + +
+

Mergely License

+

+ All Mergely code is Copyright 2014 by Jamie Peabody. + Mergely is distributed under the + GPL, + LGPL + and + MPL open source licenses. + This triple copyleft licensing model avoids incompatibility with other open + source licenses. These open source licenses are specially indicated for: +

    +
  • Integrating Mergely into Open Source software;
  • +
  • Personal and educational use of Mergely;
  • +
  • + Integrating Mergely in commercial software, taking care of satisfying + the Open Source licenses terms, while not able or interested on supporting + Mergely and its development. +
  • +
+

+

Mergely Commercial License - Closed Distribution License - CDL

+

+ You may contact Jamie Peabody to enquire about + obtaining a CDL license. +

+

+ This license offers a very flexible way to integrate Mergely in your commercial + application. These are the main advantages it offers over an Open Source license: +

+

+ Modifications and enhancements do not need to be released under an Open + Source license; There is no need to distribute any Open Source license terms + along with your product and no reference to it have to be done; You do not have + to mention any reference to Mergely in your product; Mergely source code does not + have to be distributed with your product; You can remove any file from Mergely + when integrating it with your product. +

+

+ The CDL is a lifetime license valid for all previous releases of Mergely published + prior to the year of purchase, and any releases in the following year. Please select + the license option that best fit your needs above. It includes 1 year of + personal e-mail support. +

+

Third party codes

+

+ Mergely utilizes CodeMirror, a third-party library released under an + MIT + license. Also used is jQuery and is released under the + MIT or + GPL Version 2 license. +

+
+ + +
+ +
+ + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,258 @@ +Kallithea License +================= + +Kallithea as a whole is copyrighted by various authors and is licensed under +the terms of the GNU General Public License, version 3 (GPLv3), which is a +license published by the Free Software Foundation, +Inc. [A copy of GPLv3](/COPYING) is included herein. + +Some individual files have copyright notices and those who offer changes to +those files should update the copyright notices in those specific files if +they so chose. + +However, the definitive list of copyright holders for this project is kept in +[the about page template](kallithea/templates/about.html) so that it is +displayed appropriately when Kallithea is installed. This is the most +important place to update copyright notices. + +Third-Party Code Incorporated in Kallithea +========================================== + +Various third-party code under GPLv3-compatible licenses is included as part +of Kallithea. + + + +Bootstrap +--------- + +Kallithea incorporates parts of the Javascript system called +[Bootstrap](http://getbootstrap.com/), which is: + +Copyright © 2012 Twitter, Inc. + +and licensed under +[the Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). + +A copy of the Apache License 2.0 is also included in this distribution in its +entirety in the file Apache-License-2.0.txt + + + +Codemirror +---------- + +Kallithea incorporates parts of the Javascript system called +[Codemirror](http://codemirror.net/), which is primarily: + +Copyright © 2013 by Marijn Haverbeke + +and licensed under the MIT-permissive license, which is +[included in this distribution](MIT-Permissive-License.txt). + +Additional files from upstream Codemirror are copyrighted by various authors +and licensed under other permissive licenses. The sub-directories under +[.../public/js/mode/](kallithea/public/js/mode) include the copyright and +license notice and information as they appeared in Codemirror's upstream +release. + + + +jQuery +------ + +Kallithea incorporates the Javascript system called +[jQuery](http://jquery.org/), +[herein](kallithea/public/js/jquery-1.10.2.min.js), and the Corresponding +Source can be found in https://github.com/jquery/jquery at tag 1.10.2 +(mirrored at https://kallithea-scm.org/repos/mirror/jquery/files/1.10.2/ ). + +It is Copyright 2013 jQuery Foundation and other contributors http://jquery.com/ and is under an +[MIT-permissive license](MIT-Permissive-License.txt). + + + +Mousetrap +--------- + +Kallithea incorporates parts of the Javascript system called +[Mousetrap](http://craig.is/killing/mice/), which is: + + Copyright 2013 Craig Campbell + +and licensed under +[the Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). + +A [copy of the Apache License 2.0](Apache-License-2.0.txt) is also included +in this distribution. + + + +Mergely +------- + +Kallithea incorporates some code from the Javascript system called +[Mergely](http://http://www.mergely.com/). +[Mergely's license](http://www.mergely.com/license.php), a +[copy of which is included in this repository](LICENSE-MERGELY.html), +is (GPL|LGPL|MPL). Kallithea as GPLv3'd project chooses the GPL arm of that +tri-license. + + + +Select2 +------- + +Kallithea incorporates parts of the Javascript system called +[Select2](http://ivaynberg.github.io/select2/), which is: + +Copyright 2012 Igor Vaynberg (and probably others) + +and is licensed [under the following license](https://github.com/ivaynberg/select2/blob/master/LICENSE): + +> This software is licensed under the Apache License, Version 2.0 (the +> "Apache License") or the GNU General Public License version 2 (the "GPL +> License"). You may choose either license to govern your use of this +> software only upon the condition that you accept all of the terms of either +> the Apache License or the GPL License. + +A [copy of the Apache License 2.0](Apache-License-2.0.txt) is also included +in this distribution. + +Kallithea will take the Apache license fork of the dual license, since +Kallithea is GPLv3'd. + + + +Select2-Bootstrap-CSS +--------------------- + +Kallithea incorporates some CSS from a system called +[Select2-bootstrap-css](https://github.com/t0m/select2-bootstrap-css), which +is: + +Copyright © 2013 Tom Terrace (and likely others) + +and licensed under the MIT-permissive license, which is +[included in this distribution](MIT-Permissive-License.txt). + + + +History.js +---------- + +Kallithea incorporates some CSS from a system called History.js, which is + +Copyright 2010-2011 Benjamin Arthur Lupton + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + + +YUI +--- + +Kallithea incorporates parts of the Javascript system called +[YUI 2 — Yahoo! User Interface Library](http://yui.github.io/yui2/docs/yui_2.9.0_full/), +which is made available under the [BSD License](http://yuilibrary.com/license/): + +Copyright © 2013 Yahoo! Inc. All rights reserved. + +Redistribution and use of this software in source and binary forms, with or +without modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of Yahoo! Inc. nor the names of YUI's contributors may be + used to endorse or promote products derived from this software without + specific prior written permission of Yahoo! Inc. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Kallithea includes a minified version of YUI 2.9. To build yui.2.9.js: + + git clone https://github.com/yui/builder + git clone https://github.com/yui/yui2 + cd yui2/ + git checkout hudson-yui2-2800 + ln -sf JumpToPageDropDown.js src/paginator/js/JumpToPageDropdown.js # work around inconsistent casing + rm -f tmp.js + for m in yahoo event dom connection animation dragdrop element datasource autocomplete container event-delegate json datatable paginator; do + rm -f build/\$m/\$m.js + ( cd src/\$m && ant build deploybuild ) && sed -e 's,@VERSION@,2.9.0,g' -e 's,@BUILD@,2800,g' build/\$m/\$m.js >> tmp.js + done + java -jar ../builder/componentbuild/lib/yuicompressor/yuicompressor-2.4.4.jar tmp.js -o yui.2.9.js + +In compliance with GPLv3 the Corresponding Source for this Object Code is made +available on +[https://kallithea-scm.org/repos/mirror](https://kallithea-scm.org/repos/mirror). + + + +Flot +---- + +Kallithea incorporates some CSS from a system called +[Flot](http://code.google.com/p/flot/), which is: + +Copyright 2006 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +A [copy of the Apache License 2.0](Apache-License-2.0.txt) is also included +in this distribution. + + + +Migrate +------- + +Kallithea incorporates in kallithea/lib/dbmigrate/migrate parts of the Python +system called [Migrate or sqlalchemy-migrate](https://github.com/stackforge/sqlalchemy-migrate), +which is: + +Copyright (c) 2009 Evan Rosson, Jan Dittberner, Domen Kožar + +and licensed under the MIT-permissive license, which is +[included in this distribution](MIT-Permissive-License.txt). + + + +EOF diff --git a/MANIFEST.in b/MANIFEST.in --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,8 +1,8 @@ -include rhodecode/config/deployment.ini_tmpl -include rhodecode/lib/dbmigrate/migrate.cfg +include kallithea/config/deployment.ini_tmpl +include kallithea/lib/dbmigrate/migrate.cfg include README.rst -recursive-include rhodecode/i18n * +recursive-include kallithea/i18n * #docs recursive-include docs * @@ -11,9 +11,9 @@ recursive-include docs * recursive-include init.d * #images -recursive-include rhodecode/public/css * -recursive-include rhodecode/public/images * +recursive-include kallithea/public/css * +recursive-include kallithea/public/images * #js -recursive-include rhodecode/public/js * +recursive-include kallithea/public/js * #templates -recursive-include rhodecode/templates * +recursive-include kallithea/templates * diff --git a/MIT-Permissive-License.txt b/MIT-Permissive-License.txt new file mode 100644 --- /dev/null +++ b/MIT-Permissive-License.txt @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -1,71 +1,57 @@ ========= -RhodeCode +Kallithea ========= About ----- -``RhodeCode`` is a fast and powerful management tool for Mercurial_ and GIT_ +``Kallithea`` is a fast and powerful management tool for Mercurial_ and GIT_ with a built in push/pull server, full text search and code-review. It works on http/https and has a built in permission/authentication system with -the ability to authenticate via LDAP or ActiveDirectory. RhodeCode also provides +the ability to authenticate via LDAP or ActiveDirectory. Kallithea also provides simple API so it's easy integrable with existing external systems. -RhodeCode is similar in some respects to github_ or bitbucket_, -however RhodeCode can be run as standalone hosted application on your own server. +Kallithea is similar in some respects to github_ or bitbucket_, +however Kallithea can be run as standalone hosted application on your own server. It is open source and donation ware and focuses more on providing a customized, self administered interface for Mercurial_ and GIT_ repositories. -RhodeCode works on \*nix systems and Windows it is powered by a vcs_ library +Kallithea works on \*nix systems and Windows it is powered by a vcs_ library that Lukasz Balcerzak and Marcin Kuzminski created to handle multiple different version control systems. -RhodeCode uses `PEP386 versioning `_ +Kallithea was forked from RhodeCode in July 2014 and has been heavily modified. Installation ------------ -Stable releases of RhodeCode are best installed via:: +Stable releases of Kallithea are best installed via:: - easy_install rhodecode + easy_install kallithea Or:: - pip install rhodecode + pip install kallithea Detailed instructions and links may be found on the Installation page. -Please visit http://packages.python.org/RhodeCode/installation.html for +Please visit http://packages.python.org/Kallithea/installation.html for more details -RhodeCode demo --------------- - -http://demo.rhodecode.org - -The default access is anonymous but you can login to an administrative account -using the following credentials: - -- username: demo -- password: demo12 Source code ----------- -The latest sources can be obtained from official RhodeCode instance -https://secure.rhodecode.org +The latest sources can be obtained from https://kallithea-scm.org/repos/kallithea MIRRORS: Issue tracker and sources at bitbucket_ -http://bitbucket.org/marcinkuzminski/rhodecode - -Sources at github_ - -https://github.com/marcinkuzminski/rhodecode +https://bitbucket.org/conservancy/kallithea -RhodeCode Features + +Kallithea Features ------------------ - Has its own middleware to handle mercurial_ and git_ protocol requests. @@ -82,7 +68,7 @@ RhodeCode Features - Built in Gist functionality for sharing code snippets. - Integrates easily with other systems, with custom created mappers you can connect it to almost any issue tracker, and with an JSON-RPC API you can make much more -- Build in commit-api let's you add, edit and commit files right from RhodeCode +- Build in commit-api let's you add, edit and commit files right from Kallithea web interface using simple editor or upload binary files using simple form. - Powerfull pull-request driven review system with inline commenting, changeset statuses, and notification system. @@ -127,7 +113,7 @@ Incoming / Plans License ------- -``RhodeCode`` is released under the GPLv3 license. +``Kallithea`` is released under the GPLv3 license. Getting help @@ -140,24 +126,20 @@ Listed bellow are various support resour Please try to read the documentation before posting any issues, especially the **troubleshooting section** -- Join the `Google group `_ and ask - any questions. - -- Open an issue at `issue tracker `_ +- Open an issue at `issue tracker `_ -- Join #rhodecode on FreeNode (irc.freenode.net) - or use http://webchat.freenode.net/?channels=rhodecode for web access to irc. +- Join #kallithea on FreeNode (irc.freenode.net) + or use http://webchat.freenode.net/?channels=kallithea for web access to irc. -- You can also follow me on twitter **@marcinkuzminski** where i often post some - news about RhodeCode +You can follow this project on Twitter, **@KallitheaSCM**. Online documentation -------------------- -Online documentation for the current version of RhodeCode is available at - - http://packages.python.org/RhodeCode/ - - http://rhodecode.readthedocs.org/en/latest/index.html +Online documentation for the current version of Kallithea is available at + - http://packages.python.org/Kallithea/ + - http://kallithea.readthedocs.org/ You may also build the documentation for yourself - go into ``docs/`` and run:: @@ -167,6 +149,50 @@ You may also build the documentation for have sphinx_ installed you can install it via the command: ``easy_install sphinx``) + +Converting from RhodeCode +------------------------- + +Currently, you have two options for working with an existing RhodeCode database: + - keep the database unconverted (intended for testing and evaluation) + - convert the database in a one-time step + +Maintaining Interoperability +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interoperability with RhodeCode 2.2.5 installations is provided so you don't +have to immediately commit to switching to Kallithea. This option will most +likely go away once the two projects have diverged significantly. + +To run Kallithea on a Rhodecode database, run:: + + echo "BRAND = 'rhodecode'" > kallithea/brand.py + +This location will depend on where you installed Kallithea. If you installed via:: + + python setup.py install + +then you will find this location at +``$VIRTUAL_ENV/lib/python2.7/site-packages/Kallithea-2.2.5-py2.7.egg/kallithea`` + +One-time Conversion +~~~~~~~~~~~~~~~~~~~ + +Alternatively, if you would like to convert the database for good, you can use +a helper script provided by Kallithea. This script will operate directly on the +database, using the database string you can find in your ``production.ini`` (or +``development.ini``) file. For example, if using SQLite:: + + cd /path/to/kallithea + cp /path/to/rhodecode/rhodecode.db kallithea.db + pip install sqlalchemy-migrate + python kallithea/bin/rebranddb.py sqlite:///kallithea.db + +.. WARNING:: + + If you used the other method for interoperability, overwrite brand.py with + an empty file (or watch out for stray brand.pyc after removing brand.py). + .. _virtualenv: http://pypi.python.org/pypi/virtualenv .. _python: http://www.python.org/ .. _sphinx: http://sphinx.pocoo.org/ diff --git a/development.ini b/development.ini --- a/development.ini +++ b/development.ini @@ -1,23 +1,30 @@ ################################################################################ ################################################################################ -# RhodeCode - Pylons environment configuration # +# Kallithea - Development config: # +# listening on *:5000 # +# sqlite and kallithea.db # +# initial_repo_scan = true # +# set debug = true # +# verbose and colorful logging # # # # The %(here)s variable will be replaced with the parent directory of this file# ################################################################################ +################################################################################ [DEFAULT] debug = true pdebug = false + ################################################################################ ## Uncomment and replace with the address which should receive ## ## any error reports after application crash ## -## Additionally those settings will be used by RhodeCode mailing system ## +## Additionally those settings will be used by Kallithea mailing system ## ################################################################################ #email_to = admin@localhost #error_email_from = paste_error@localhost -#app_email_from = rhodecode-noreply@localhost +#app_email_from = kallithea-noreply@localhost #error_message = -#email_prefix = [RhodeCode] +#email_prefix = [Kallithea] #smtp_server = mail.server.com #smtp_username = @@ -54,11 +61,11 @@ max_request_body_size = 107374182400 ## is set to more than one worker #workers = 1 ## process name -#proc_name = rhodecode +#proc_name = kallithea ## type of worker class, one of sync, eventlet, gevent, tornado ## recommended for bigger setup is using of of other than sync one #worker_class = sync -#max_requests = 5 +#max_requests = 1000 ## ammount of time a worker can handle request before it gets killed and ## restarted #timeout = 3600 @@ -68,13 +75,13 @@ max_request_body_size = 107374182400 #[uwsgi] #socket = /tmp/uwsgi.sock #master = true -#http = 0.0.0.0:5000 +#http = 127.0.0.1:5000 ## set as deamon and redirect all output to file -#daemonize = ./uwsgi_rhodecode.log +#daemonize = ./uwsgi_kallithea.log ## master process PID -#pidfile = ./uwsgi_rhodecode.pid +#pidfile = ./uwsgi_kallithea.pid ## stats server with workers statistics, use uwsgitop ## for monitoring, `uwsgitop 127.0.0.1:1717` @@ -133,27 +140,28 @@ port = 5000 #prefix = / [app:main] -use = egg:rhodecode +use = egg:kallithea ## enable proxy prefix middleware #filter-with = proxy-prefix full_stack = true static_files = true -## Optional Languages -## en, fr, ja, pt_BR, zh_CN, zh_TW, pl +## Available Languages: +## de en fr ja pl pt_BR ru zh_CN zh_TW lang = en cache_dir = %(here)s/data index_dir = %(here)s/data/index ## perform a full repository scan on each server start, this should be ## set to false after first startup, to allow faster server restarts. +#initial_repo_scan = false initial_repo_scan = true ## uncomment and set this path to use archive download cache -#archive_cache_dir = /tmp/tarballcache +archive_cache_dir = %(here)s/tarballcache ## change this to unique ID for security -app_instance_uuid = rc-production +app_instance_uuid = development-not-secret ## cut off limit for large diffs (size in bytes) cut_off_limit = 256000 @@ -161,7 +169,7 @@ cut_off_limit = 256000 ## use cache version of scm repo everywhere vcs_full_cache = true -## force https in RhodeCode, fixes https redirects, assumes it's always https +## force https in Kallithea, fixes https redirects, assumes it's always https force_https = false ## use Strict-Transport-Security headers @@ -178,7 +186,7 @@ git_path = git ## git rev filter option, --all is the default filter, if you need to ## hide all refs in changelog switch this to --branches --tags -git_rev_filter=--all +#git_rev_filter = --branches --tags ## RSS feed options rss_cut_off_limit = 256000 @@ -191,8 +199,8 @@ show_revision_number = true ## gist URL alias, used to create nicer urls for gist. This should be an ## url that does rewrites to _admin/gists/. -## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal -## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/ +## example: http://gist.kallithea.server/{gistid}. Empty means use the internal +## Kallithea url, ie. http[s]://your.kallithea.server/_admin/gists/ gist_alias_url = ## white list of API enabled controllers. This allows to add list of @@ -200,7 +208,7 @@ gist_alias_url = ## api access to raw_files put `FilesController:raw`, to enable access to patches ## add `ChangesetController:changeset_patch`. This list should be "," separated ## Syntax is :. Check debug logs for generated names -## Recommended settings bellow are commented out: +## Recommended settings below are commented out: api_access_controllers_whitelist = # ChangesetController:changeset_patch, # ChangesetController:changeset_raw, @@ -212,8 +220,8 @@ api_access_controllers_whitelist = ## {email} user email ## {md5email} md5 hash of the user email (like at gravatar.com) ## {size} size of the image that is expected from the server application -## {scheme} http/https from RhodeCode server -## {netloc} network location from RhodeCode server +## {scheme} http/https from Kallithea server +## {netloc} network location from Kallithea server #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size} #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size} @@ -236,8 +244,8 @@ default_encoding = utf8 #clone_uri = {scheme}://{user}{pass}{netloc}{path} -## issue tracker for RhodeCode (leave blank to disable, absent for default) -#bugtracker = http://bitbucket.org/marcinkuzminski/rhodecode/issues +## issue tracker for Kallithea (leave blank to disable, absent for default) +#bugtracker = https://bitbucket.org/conservancy/kallithea/issues ## issue tracking mapping for commits messages ## comment out issue_pat, issue_server, issue_prefix to enable @@ -262,7 +270,7 @@ issue_prefix = # ## issue_pat, issue_server_link, issue_prefix can have suffixes to specify ## multiple patterns, to other issues server, wiki or others ## below an example how to create a wiki pattern -# #wiki-some-id -> https://mywiki.com/some-id +# wiki-some-id -> https://mywiki.com/some-id #issue_pat_wiki = (?:wiki-)(.+) #issue_server_link_wiki = https://mywiki.com/{id} @@ -271,8 +279,8 @@ issue_prefix = # ## instance-id prefix ## a prefix key for this instance used for cache invalidation when running -## multiple instances of rhodecode, make sure it's globally unique for -## all running rhodecode instances. Leave empty if you don't use it +## multiple instances of kallithea, make sure it's globally unique for +## all running kallithea instances. Leave empty if you don't use it instance_id = ## alternative return HTTP header for failed authentication. Default HTTP @@ -294,6 +302,7 @@ allow_custom_hooks_settings = True #################################### ### CELERY CONFIG #### #################################### + use_celery = false broker.host = localhost broker.vhost = rabbitmqhost @@ -301,7 +310,7 @@ broker.port = 5672 broker.user = rabbitmq broker.password = qweqwe -celery.imports = rhodecode.lib.celerylib.tasks +celery.imports = kallithea.lib.celerylib.tasks celery.result.backend = amqp celery.result.dburi = amqp:// @@ -321,6 +330,7 @@ celery.always.eager = false #################################### ### BEAKER CACHE #### #################################### + beaker.cache.data_dir=%(here)s/data/cache/data beaker.cache.lock_dir=%(here)s/data/cache/lock @@ -360,7 +370,7 @@ beaker.cache.sql_cache_long.key_length = ## db session ## #beaker.session.type = ext:database -#beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode +#beaker.session.sa.url = postgresql://postgres:qwe@localhost/kallithea #beaker.session.table_name = db_session ## encrypted cookie client side session, good for many instances ## @@ -369,8 +379,8 @@ beaker.cache.sql_cache_long.key_length = ## file based cookies (default) ## #beaker.session.type = file -beaker.session.key = rhodecode -beaker.session.secret = develop-rc-uytcxaz +beaker.session.key = kallithea +beaker.session.secret = development-not-secret ## Secure encrypted cookie. Requires AES and AES python libraries ## you must disable beaker.session.secret to use this @@ -400,7 +410,7 @@ beaker.session.auto = False ### [errormator] ### #################### -## Errormator is tailored to work with RhodeCode, see +## Errormator is tailored to work with Kallithea, see ## http://errormator.com for details how to obtain an account ## you must install python package `errormator_client` to make it work @@ -479,10 +489,12 @@ sentry.exclude_paths = ## execute malicious code after an exception is raised. ## ################################################################################ #set debug = false +set debug = true ################################## ### LOGVIEW CONFIG ### ################################## + logview.sqlalchemy = #faa logview.pylons.templating = #bfb logview.pylons.util = #eee @@ -490,9 +502,18 @@ logview.pylons.util = #eee ######################################################### ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ### ######################################################### -#sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30 -sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode -#sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode + +# SQLITE [default] +sqlalchemy.db1.url = sqlite:///%(here)s/kallithea.db?timeout=60 + +# POSTGRESQL +# sqlalchemy.db1.url = postgresql://user:pass@localhost/kallithea + +# MySQL +# sqlalchemy.db1.url = mysql://user:pass@localhost/kallithea + +# see sqlalchemy docs for others + sqlalchemy.db1.echo = false sqlalchemy.db1.pool_recycle = 3600 sqlalchemy.db1.convert_unicode = true @@ -500,8 +521,9 @@ sqlalchemy.db1.convert_unicode = true ################################ ### LOGGING CONFIGURATION #### ################################ + [loggers] -keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer +keys = root, routes, kallithea, sqlalchemy, beaker, templates, whoosh_indexer [handlers] keys = console, console_sql @@ -512,6 +534,7 @@ keys = generic, color_formatter, color_f ############# ## LOGGERS ## ############# + [logger_root] level = NOTSET handlers = console @@ -535,10 +558,10 @@ handlers = qualname = pylons.templating propagate = 1 -[logger_rhodecode] +[logger_kallithea] level = DEBUG handlers = -qualname = rhodecode +qualname = kallithea propagate = 1 [logger_sqlalchemy] @@ -560,12 +583,16 @@ propagate = 1 [handler_console] class = StreamHandler args = (sys.stderr,) +#level = INFO +#formatter = generic level = DEBUG formatter = color_formatter [handler_console_sql] class = StreamHandler args = (sys.stderr,) +#level = WARN +#formatter = generic level = DEBUG formatter = color_formatter_sql @@ -578,11 +605,11 @@ format = %(asctime)s.%(msecs)03d %(level datefmt = %Y-%m-%d %H:%M:%S [formatter_color_formatter] -class=rhodecode.lib.colored_formatter.ColorFormatter +class=kallithea.lib.colored_formatter.ColorFormatter format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s datefmt = %Y-%m-%d %H:%M:%S [formatter_color_formatter_sql] -class=rhodecode.lib.colored_formatter.ColorFormatterSql +class=kallithea.lib.colored_formatter.ColorFormatterSql format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s datefmt = %Y-%m-%d %H:%M:%S diff --git a/docs/Makefile b/docs/Makefile --- a/docs/Makefile +++ b/docs/Makefile @@ -72,17 +72,17 @@ qthelp: @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/RhodeCode.qhcp" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Kallithea.qhcp" @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/RhodeCode.qhc" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Kallithea.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/RhodeCode" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/RhodeCode" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Kallithea" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Kallithea" @echo "# devhelp" epub: diff --git a/docs/api/api.rst b/docs/api/api.rst --- a/docs/api/api.rst +++ b/docs/api/api.rst @@ -5,15 +5,15 @@ API === -Starting from RhodeCode version 1.2 a simple API was implemented. +Starting from Kallithea version 1.2 a simple API was implemented. There's a single schema for calling all api methods. API is implemented -with JSON protocol both ways. An url to send API request to RhodeCode is +with JSON protocol both ways. An url to send API request to Kallithea is /_admin/api API ACCESS FOR WEB VIEWS ++++++++++++++++++++++++ -API access can also be turned on for each web view in RhodeCode that is +API access can also be turned on for each web view in Kallithea that is decorated with `@LoginRequired` decorator. To enable API access simple change the standard login decorator to `@LoginRequired(api_access=True)`. @@ -21,7 +21,7 @@ To make this operation easier, starting of views that will have API access enabled. Simply edit `api_access_controllers_whitelist` option in your .ini file, and define views that should have API access enabled. Following example shows how to enable API access to patch/diff raw file and archive -in RhodeCode:: +in Kallithea:: api_access_controllers_whitelist = ChangesetController:changeset_patch, @@ -30,7 +30,7 @@ in RhodeCode:: FilesController:archivefile -After this change, a rhodecode view can be accessed without login by adding a +After this change, a Kallithea view can be accessed without login by adding a GET parameter `?api_key=` to url. By default this is only enabled on RSS/ATOM feed views. Exposing raw diffs is a good way to integrate with 3rd party services like code review, or build farms that could download archives. @@ -62,7 +62,7 @@ Simply provide api_key can be found in your user account page -RhodeCode API will return always a JSON-RPC response:: +Kallithea API will return always a JSON-RPC response:: { "id":, # matching id sent by request @@ -78,13 +78,13 @@ and result will be null. API CLIENT ++++++++++ -From version 1.4 RhodeCode adds a script that allows to easily -communicate with API. After installing RhodeCode a `rhodecode-api` script +From version 1.4 Kallithea adds a script that allows to easily +communicate with API. After installing Kallithea a `kallithea-api` script will be available. To get started quickly simply run:: - rhodecode-api _create_config --apikey= --apihost= + kallithea-api _create_config --apikey= --apihost= This will create a file named .config in the directory you executed it storing json config file with credentials. You can skip this step and always provide @@ -93,10 +93,10 @@ both of the arguments to be able to comm after that simply run any api command for example get_repo:: - rhodecode-api get_repo + kallithea-api get_repo calling {"api_key": "", "id": 75, "args": {}, "method": "get_repo"} to http://127.0.0.1:5000 - rhodecode said: + Kallithea said: {'error': 'Missing non optional `repoid` arg in JSON DATA', 'id': 75, 'result': None} @@ -105,10 +105,10 @@ Ups looks like we forgot to add an argum Let's try again now giving the repoid as parameters:: - rhodecode-api get_repo repoid:rhodecode + kallithea-api get_repo repoid:myrepo - calling {"api_key": "", "id": 39, "args": {"repoid": "rhodecode"}, "method": "get_repo"} to http://127.0.0.1:5000 - rhodecode said: + calling {"api_key": "", "id": 39, "args": {"repoid": "myrepo"}, "method": "get_repo"} to http://127.0.0.1:5000 + Kallithea said: {'error': None, 'id': 39, 'result': } @@ -146,7 +146,7 @@ rescan_repos ------------ Dispatch rescan repositories action. If remove_obsolete is set -RhodeCode will delete repos that are in database but not in the filesystem. +Kallithea will delete repos that are in database but not in the filesystem. This command can be executed only using api_key belonging to user with admin rights. @@ -225,7 +225,7 @@ OUTPUT:: show_ip ------- -Shows IP address as seen from RhodeCode server, together with all +Shows IP address as seen from Kallithea server, together with all defined IP addresses for given user. This command can be executed only using api_key belonging to user with admin rights. diff --git a/docs/api/models.rst b/docs/api/models.rst --- a/docs/api/models.rst +++ b/docs/api/models.rst @@ -4,32 +4,32 @@ The :mod:`models` Module ======================== -.. automodule:: rhodecode.model +.. automodule:: kallithea.model :members: -.. automodule:: rhodecode.model.comment +.. automodule:: kallithea.model.comment :members: -.. automodule:: rhodecode.model.notification +.. automodule:: kallithea.model.notification :members: -.. automodule:: rhodecode.model.permission +.. automodule:: kallithea.model.permission :members: -.. automodule:: rhodecode.model.repo_permission +.. automodule:: kallithea.model.repo_permission :members: -.. automodule:: rhodecode.model.repo +.. automodule:: kallithea.model.repo :members: -.. automodule:: rhodecode.model.repos_group +.. automodule:: kallithea.model.repo_group :members: -.. automodule:: rhodecode.model.scm +.. automodule:: kallithea.model.scm :members: -.. automodule:: rhodecode.model.user +.. automodule:: kallithea.model.user :members: -.. automodule:: rhodecode.model.users_group +.. automodule:: kallithea.model.user_group :members: diff --git a/docs/changelog.rst b/docs/changelog.rst --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,1225 +4,6 @@ Changelog ========= - -1.7.2 (**2013-07-XX**) ----------------------- - -news -++++ - -- Added handling of copied files in diffs -- Implemented issue #387 side-by-side diffs view -- Added option to specify other than official bugtracker url to post issues - with RhodeCode. -- Markdown renderer now uses github flavored syntax with a better newline handling -- Added User pre-create, create and delete hooks for rcextensions. -- Branch selectors: show closed branches too for Mercurial -- Updated codemirror to latest version and added syntax coloring dropdown for - various languages CodeMirror supports -- Added --no-public-access / --public-access flags into setup-rhodecode - command to enable setup without public access -- Various small updates to pull requests -- Bumped Mercurial version to latest -- Diffs view doesn't show content of delete files anymore. - -fixes -+++++ - -- Added missing __get_cs_or_redirect method for file history. - Fixes issue with displaying a history of file that is not present at tip. -- Pull request: urlify description and fix javascript injection -- Fixed some missing IP extraction for action logger -- Fixed bug with log_delete hook didn't properly store - user who triggered delete action -- Fixed show as raw link for private gists -- Fixes issue #860. IMC web commits poisoned caches when they failed with commit. -- Fixes issue #856 file upload >1000 bytes on windows throws exception. - - -1.7.1 (**2013-06-13**) ----------------------- - -news -++++ - -- Apply to children flag on repository group also adds users to private - repositories, this is now consistent with user groups. Private repos default - permissions are not affected by apply to children flag. -- Removed unionrepo code as it's part of Mercurial 2.6 -- RhodeCode accepts now read only paths for serving repositories. - -fixes -+++++ - -- Fixed issues with how mysql handles float values. Caused gists with - expiration dates not work properly on mysql. -- Fixed issue with ldap enable/disable flag - - -1.7.0 (**2013-06-08**) ----------------------- - -news -++++ - -- Manage User’s Groups(teams): create, delete, rename, add/remove users inside. - by delegated user group admins. -- Implemented simple Gist functionality. -- External authentication got special flag to controll user activation. -- Created whitelist for API access. Each view can now be accessed by api_key - if added to whitelist. -- Added dedicated file history page. -- Added compare option into bookmarks -- Improved diff display for binary files and renames. -- Archive downloading are now stored in main action journal. -- Switch gravatar to always use ssl. -- Implements #842 RhodeCode version disclosure. -- Allow underscore to be the optionally first character of username. - -fixes -+++++ - -- #818: Bookmarks Do Not Display on Changeset View. -- Fixed default permissions population during upgrades. -- Fixed overwrite default user group permission flag. -- Fixed issue with h.person() function returned prematurly giving only email - info from changeset metadata. -- get_changeset uses now mercurial revrange to filter out branches. - Switch to branch it's around 20% faster this way. -- Fixed some issues with paginators on chrome. -- Forbid changing of repository type. -- Adde missing permission checks in list of forks in repository settings. -- Fixes #834 hooks error on remote pulling. -- Fixes issues #849. Web Commits functionality failed for non-ascii files. -- Fixed #850. Whoosh indexer should use the default revision when doing index. -- Fixed #851 and #563 make-index crashes on non-ascii files. -- Fixes #852, flash messages had issies with non-ascii messages - - -1.6.0 (**2013-05-12**) ----------------------- - -news -++++ - -fixes -+++++ - -- #818: Bookmarks Do Not Display on Changeset View -- Fixed issue with forks form errors rendering -- #819 review status is showed in the main changelog -- Permission update function is idempotent, and doesn't override default - permissions when doing upgrades -- Fixed some unicode problems with git file path -- Fixed broken handling of adding an htsts headers. -- Fixed redirection loop on changelog for empty repository -- Fixed issue with web-editor that didn't preserve executable bit - after editing files - - -1.6.0rc1 (**2013-04-07**) -------------------------- - -news -++++ - - - Redesign UI, with lots of small improvements. - - Group management delegation. Group admin can manage a group, and repos - under it, admin can create child groups inside group he manages. - - Repository extra fields. Optional unlimited extra fields can be defined for - each repository to store custom data. - - API get_repo call includes repo followers now. - - Large amounts of improvements in pull requests. - - #734 repo switcher is available in all pages. - - #733 API invalidate_cache function. - - Added option to turn on HSTS headers when using SSL. - - #83 show repo size on summary page. - - #745 added show full diff link into to big diff message. - - Deprecated RSS links - ATOM is the present and the future. - - Add option to define custom lexers for custom extensions for code highlight - in rcextension module. - - Git executable is now configurable via .ini files. - - #689 repositories now has optional detach/delete option for connected forks. - - Obfuscate password when cloning a remote repo with credentials. - - #788 tarball cache. zip or compressed tarballs can be optionally cached for - faster serving. - - Speed up of last_changeset extraction in VCS. - - API get_locks function. - - Configurable HTTP codes for repository locking. - - Possible to use closed branches in ?branch= in changelog. - - Linaro's ldap sync scripts. - - #797 git refs filter is now configurable via .ini file. - - New ishell paster command for easier administrative tasks. - -fixes -+++++ - - - #654 switch to handles `/` in branch/tag/bookmark names. - - #572 moved out password reset tasks from celery. - - #730 filter out repo groups choices to only ones that you have write+ access. - - #462 disable file editing when not on branch head. - - #731 update-repoinfo sometimes failed to update data when changesets were - initial commits. - - #749,#805 and #516 Removed duplication of repo settings for rhodecode admins - and repo admins. - - Global permission update with "overwrite existing settings" shouldn't - override private repositories. - - #642 added recursion limit for stats gathering. - - #739 Delete/Edit repositories should only point to admin links if the user - is an super admin. - - Fixed escaping of html in "patch" view for GIT repos. - - #747 load changeset cache after forking to refresh lightweight dashboard caches. - - Quick repo list: public/private icon control should only control icons, - not repo visibility. - - #746 UnicodeDedode errors on feed controllers. - - #756 cleanup repos didn't properly compose paths of repos to be cleaned up. - - #763 gravatar helper function should fallback into default image if somehow - email provided is empty. - - Fixes #762, LDAP and container created users are now activated based on - the registration settings in permissions. - - Cleanup would recurse into every leaf and could thus not be used on lots of - large repositories. - - Better detection of deleting groups with subgroups inside. - - Fixed issue with renaming repos group together with changing parents with - multiple nested trees. - - #594 web interface file committing executes push hooks. - - Disallow cloning from different URI's that http[s]/svn/git/hg. - - Handling of RhodeCode extra params in consistent way. - - Don't normalize path if it's empty on adding a file through web interface. - - #808 missing changesets and files should return 404 not redirect - - #809 added url quote in clone url. - - Fixed issues with importing non-ascii repo names. - - Automatically assign instance_id for host and process if it has been set to * - - Fixed multiple IP addresses in each of extracted IP. - - Lot of other small bug fixes and improvements. - - -1.5.4 (**2013-03-13**) ----------------------- - -news -++++ - - -fixes -+++++ - -- fixed webtest dependency issues -- fixed issues with celery tasks for password reset -- fixed #763 gravatar helper function should fallback into default image - if email is empty -- fixes #762 user global activation flag is also respected for LDAP created - accounts -- use password obfuscate when clonning a remote repo with credentials inside -- fixed issue with renaming repository group together with changing parents -- disallow cloning from file:/// URIs -- handle all cases with multiple IP addresses in proxy headers - - -1.5.3 (**2013-02-12**) ----------------------- - -news -++++ - -- IP restrictions now also enabled for IPv6 - -fixes -+++++ - -- fixed issues with private checkbox not always working -- fixed #746 unicodeDedode errors on feed controllers -- fixes issue #756 cleanup repos didn't properly compose paths of repos to be cleaned up. -- fixed cache invalidation issues together with vcs_full_cache option -- repo scan should skip directories with starting with '.' -- fixes for issue #731, update-repoinfo sometimes failed to update data when changesets - were initial commits -- recursive mode of setting permission skips private repositories - - -1.5.2 (**2013-01-14**) ----------------------- - -news -++++ - -- IP restrictions for users. Each user can get a set of whitelist IP+mask for - extra protection. Useful for buildbots etc. -- added full last changeset info to lightweight dashboard. lightweight dashboard - is now fully functional replacement of original dashboard. -- implemented certain API calls for non-admin users. -- enabled all Markdown Extra plugins -- implemented #725 Pull Request View - Show origin repo URL -- show comments from pull requests into associated changesets - -fixes -+++++ - -- update repoinfo script is more failsafe -- fixed #687 Lazy loaded tooltip bug with simultaneous ajax requests -- fixed #691: Notifications for pull requests: move link to top for better - readability -- fixed #699: fix missing fork docs for API -- fixed #693 Opening changeset from pull request fails -- fixed #710 File view stripping empty lines from beginning and end of file -- fixed issues with getting repos by path on windows, caused GIT hooks to fail -- fixed issues with groups paginator on main dashboard -- improved fetch/pull command for git repos, now pulling all refs -- fixed issue #719 Journal revision ID tooltip AJAX query path is incorrect - when running in a subdir -- fixed issue #702 API methods without arguments fail when "args":null -- set the status of changesets initially on pull request. Fixes issues #690 and #587 - - -1.5.1 (**2012-12-13**) ----------------------- - -news -++++ - -- implements #677: Don't allow to close pull requests when they are - under-review status -- implemented #670 Implementation of Roles in Pull Request - -fixes -+++++ - -- default permissions can get duplicated after migration -- fixed changeset status labels, they now select radio buttons -- #682 translation difficult for multi-line text -- #683 fixed difference between messages about not mapped repositories -- email: fail nicely when no SMTP server has been configured - - -1.5.0 (**2012-12-12**) ----------------------- - -news -++++ - -- new rewritten from scratch diff engine. 10x faster in edge cases. Handling - of file renames, copies, change flags and binary files -- added lightweight dashboard option. ref #500. New version of dashboard - page that doesn't use any VCS data and is super fast to render. Recommended - for large amount of repositories. -- implements #648 write Script for updating last modification time for - lightweight dashboard -- implemented compare engine for git repositories. -- LDAP failover, option to specify multiple servers -- added Errormator and Sentry support for monitoring RhodeCode -- implemented #628: Pass server URL to rc-extensions hooks -- new tooltip implementation - added lazy loading of changesets from journal - pages. This can significantly improve speed of rendering the page -- implements #632,added branch/tag/bookmarks info into feeds - added changeset link to body of message -- implemented #638 permissions overview to groups -- implements #636, lazy loading of history and authors to speed up source - pages rendering -- implemented #647, option to pass list of default encoding used to - encode to/decode from unicode -- added caching layer into RSS/ATOM feeds. -- basic implementation of cherry picking changesets for pull request, ref #575 -- implemented #661 Add option to include diff in RSS feed -- implemented file history page for showing detailed changelog for a given file -- implemented #663 Admin/permission: specify default repogroup perms -- implemented #379 defaults settings page for creation of repositories, locking - statistics, downloads, repository type -- implemented #210 filtering of admin journal based on Whoosh Query language -- added parents/children links in changeset viewref #650 - -fixes -+++++ - -- fixed git version checker -- #586 patched basic auth handler to fix issues with git behind proxy -- #589 search urlgenerator didn't properly escape special characters -- fixed issue #614 Include repo name in delete confirmation dialog -- fixed #623: Lang meta-tag doesn't work with C#/C++ -- fixes #612 Double quotes to Single quotes result in bad html in diff -- fixes #630 git statistics do too much work making them slow. -- fixes #625 Git-Tags are not displayed in Shortlog -- fix for issue #602, enforce str when setting mercurial UI object. - When this is used together with mercurial internal translation system - it can lead to UnicodeDecodeErrors -- fixes #645 Fix git handler when doing delete remote branch -- implements #649 added two seperate method for author and committer to VCS - changeset class switch author for git backed to be the real author not committer -- fix issue #504 RhodeCode is showing different versions of README on - different summary page loads -- implemented #658 Changing username in LDAP-Mode should not be allowed. -- fixes #652 switch to generator approach when doing file annotation to prevent - huge memory consumption -- fixes #666 move lockkey path location to cache_dir to ensure this path is - always writable for rhodecode server -- many more small fixes and improvements -- fixed issues with recursive scans on removed repositories that could take - long time on instance start - - -1.4.4 (**2012-10-08**) ----------------------- - -news -++++ - -- obfuscate db password in logs for engine connection string -- #574 Show pull request status also in shortlog (if any) -- remember selected tab in my account page -- Bumped mercurial version to 2.3.2 -- #595 rcextension hook for repository delete - -fixes -+++++ - -- Add git version detection to warn users that Git used in system is to - old. Ref #588 - also show git version in system details in settings page -- fixed files quick filter links -- #590 Add GET flag that controls the way the diff are generated, for pull - requests we want to use non-bundle based diffs, That are far better for - doing code reviews. The /compare url still uses bundle compare for full - comparison including the incoming changesets -- Fixed #585, checks for status of revision where to strict, and made - opening pull request with those revision impossible due to previously set - status. Checks now are made also for the repository. -- fixes #591 git backend was causing encoding errors when handling binary - files - added a test case for VCS lib tests -- fixed #597 commits in future get negative age. -- fixed #598 API docs methods had wrong members parameter as returned data - - -1.4.3 (**2012-09-28**) ----------------------- - -news -++++ - -- #558 Added config file to hooks extra data -- bumped mercurial version to 2.3.1 -- #518 added possibility of specifying multiple patterns for issues -- update codemirror to latest version - -fixes -+++++ - -- fixed #570 explicit user group permissions can overwrite owner permissions -- fixed #578 set proper PATH with current Python for Git - hooks to execute within same Python as RhodeCode -- fixed issue with Git bare repos that ends with .git in name - - -1.4.2 (**2012-09-12**) ----------------------- - -news -++++ - -- added option to menu to quick lock/unlock repository for users that have - write access to -- Implemented permissions for writing to repo - groups. Now only write access to group allows to create a repostiory - within that group -- #565 Add support for {netloc} and {scheme} to alternative_gravatar_url -- updated translation for zh_CN - -fixes -+++++ - -- fixed visual permissions check on repository groups inside groups -- fixed issues with non-ascii search terms in search, and indexers -- fixed parsing of page number in GET parameters -- fixed issues with generating pull-request overview for repos with - bookmarks and tags, also preview doesn't loose chosen revision from - select dropdown - - -1.4.1 (**2012-09-07**) ----------------------- - -news -++++ - -- always put a comment about code-review status change even if user send - empty data -- modified_on column saves repository update and it's going to be used - later for light version of main page ref #500 -- pull request notifications send much nicer emails with details about pull - request -- #551 show breadcrumbs in summary view for repositories inside a group - -fixes -+++++ - -- fixed migrations of permissions that can lead to inconsistency. - Some users sent feedback that after upgrading from older versions issues - with updating default permissions occurred. RhodeCode detects that now and - resets default user permission to initial state if there is a need for that. - Also forces users to set the default value for new forking permission. -- #535 improved apache wsgi example configuration in docs -- fixes #550 mercurial repositories comparision failed when origin repo had - additional not-common changesets -- fixed status of code-review in preview windows of pull request -- git forks were not initialized at bare repos -- fixes #555 fixes issues with comparing non-related repositories -- fixes #557 follower counter always counts up -- fixed issue #560 require push ssl checkbox wasn't shown when option was - enabled -- fixed #559 -- fixed issue #559 fixed bug in routing that mapped repo names with _ in name as - if it was a request to url by repository ID - - -1.4.0 (**2012-09-03**) ----------------------- - -news -++++ - -- new codereview system -- email map, allowing users to have multiple email addresses mapped into - their accounts -- improved git-hook system. Now all actions for git are logged into journal - including pushed revisions, user and IP address -- changed setup-app into setup-rhodecode and added default options to it. -- new git repos are created as bare now by default -- #464 added links to groups in permission box -- #465 mentions autocomplete inside comments boxes -- #469 added --update-only option to whoosh to re-index only given list - of repos in index -- rhodecode-api CLI client -- new git http protocol replaced buggy dulwich implementation. - Now based on pygrack & gitweb -- Improved RSS/ATOM feeds. Discoverable by browsers using proper headers, and - reformated based on user suggestions. Additional rss/atom feeds for user - journal -- various i18n improvements -- #478 permissions overview for admin in user edit view -- File view now displays small gravatars off all authors of given file -- Implemented landing revisions. Each repository will get landing_rev attribute - that defines 'default' revision/branch for generating readme files -- Implemented #509, RhodeCode enforces SSL for push/pulling if requested at - earliest possible call. -- Import remote svn repositories to mercurial using hgsubversion. -- Fixed #508 RhodeCode now has a option to explicitly set forking permissions -- RhodeCode can use alternative server for generating avatar icons -- implemented repositories locking. Pull locks, push unlocks. Also can be done - via API calls -- #538 form for permissions can handle multiple users at once - -fixes -+++++ - -- improved translations -- fixes issue #455 Creating an archive generates an exception on Windows -- fixes #448 Download ZIP archive keeps file in /tmp open and results - in out of disk space -- fixes issue #454 Search results under Windows include proceeding - backslash -- fixed issue #450. Rhodecode no longer will crash when bad revision is - present in journal data. -- fix for issue #417, git execution was broken on windows for certain - commands. -- fixed #413. Don't disable .git directory for bare repos on deleting -- fixed issue #459. Changed the way of obtaining logger in reindex task. -- fixed #453 added ID field in whoosh SCHEMA that solves the issue of - reindexing modified files -- fixed #481 rhodecode emails are sent without Date header -- fixed #458 wrong count when no repos are present -- fixed issue #492 missing `\ No newline at end of file` test at the end of - new chunk in html diff -- full text search now works also for commit messages - - -1.3.6 (**2012-05-17**) ----------------------- - -news -++++ - -- chinese traditional translation -- changed setup-app into setup-rhodecode and added arguments for auto-setup - mode that doesn't need user interaction - -fixes -+++++ - -- fixed no scm found warning -- fixed __future__ import error on rcextensions -- made simplejson required lib for speedup on JSON encoding -- fixes #449 bad regex could get more than revisions from parsing history -- don't clear DB session when CELERY_EAGER is turned ON - - -1.3.5 (**2012-05-10**) ----------------------- - -news -++++ - -- use ext_json for json module -- unified annotation view with file source view -- notification improvements, better inbox + css -- #419 don't strip passwords for login forms, make rhodecode - more compatible with LDAP servers -- Added HTTP_X_FORWARDED_FOR as another method of extracting - IP for pull/push logs. - moved all to base controller -- #415: Adding comment to changeset causes reload. - Comments are now added via ajax and doesn't reload the page -- #374 LDAP config is discarded when LDAP can't be activated -- limited push/pull operations are now logged for git in the journal -- bumped mercurial to 2.2.X series -- added support for displaying submodules in file-browser -- #421 added bookmarks in changelog view - -fixes -+++++ - -- fixed dev-version marker for stable when served from source codes -- fixed missing permission checks on show forks page -- #418 cast to unicode fixes in notification objects -- #426 fixed mention extracting regex -- fixed remote-pulling for git remotes remopositories -- fixed #434: Error when accessing files or changesets of a git repository - with submodules -- fixed issue with empty APIKEYS for users after registration ref. #438 -- fixed issue with getting README files from git repositories - - -1.3.4 (**2012-03-28**) ----------------------- - -news -++++ - -- Whoosh logging is now controlled by the .ini files logging setup -- added clone-url into edit form on /settings page -- added help text into repo add/edit forms -- created rcextensions module with additional mappings (ref #322) and - post push/pull/create repo hooks callbacks -- implemented #377 Users view for his own permissions on account page -- #399 added inheritance of permissions for user group on repository groups -- #401 repository group is automatically pre-selected when adding repos - inside a repository group -- added alternative HTTP 403 response when client failed to authenticate. Helps - solving issues with Mercurial and LDAP -- #402 removed group prefix from repository name when listing repositories - inside a group -- added gravatars into permission view and permissions autocomplete -- #347 when running multiple RhodeCode instances, properly invalidates cache - for all registered servers - -fixes -+++++ +Kallithea project doesn't keep its changelog here. We refer you to our Mercurial logs_ . -- fixed #390 cache invalidation problems on repos inside group -- fixed #385 clone by ID url was loosing proxy prefix in URL -- fixed some unicode problems with waitress -- fixed issue with escaping < and > in changeset commits -- fixed error occurring during recursive group creation in API - create_repo function -- fixed #393 py2.5 fixes for routes url generator -- fixed #397 Private repository groups shows up before login -- fixed #396 fixed problems with revoking users in nested groups -- fixed mysql unicode issues + specified InnoDB as default engine with - utf8 charset -- #406 trim long branch/tag names in changelog to not break UI - - -1.3.3 (**2012-03-02**) ----------------------- - -news -++++ - - -fixes -+++++ - -- fixed some python2.5 compatibility issues -- fixed issues with removed repos was accidentally added as groups, after - full rescan of paths -- fixes #376 Cannot edit user (using container auth) -- fixes #378 Invalid image urls on changeset screen with proxy-prefix - configuration -- fixed initial sorting of repos inside repo group -- fixes issue when user tried to resubmit same permission into user/user_groups -- bumped beaker version that fixes #375 leap error bug -- fixed raw_changeset for git. It was generated with hg patch headers -- fixed vcs issue with last_changeset for filenodes -- fixed missing commit after hook delete -- fixed #372 issues with git operation detection that caused a security issue - for git repos - - -1.3.2 (**2012-02-28**) ----------------------- - -news -++++ - - -fixes -+++++ - -- fixed git protocol issues with repos-groups -- fixed git remote repos validator that prevented from cloning remote git repos -- fixes #370 ending slashes fixes for repo and groups -- fixes #368 improved git-protocol detection to handle other clients -- fixes #366 When Setting Repository Group To Blank Repo Group Wont Be - Moved To Root -- fixes #371 fixed issues with beaker/sqlalchemy and non-ascii cache keys -- fixed #373 missing cascade drop on user_group_to_perm table - - -1.3.1 (**2012-02-27**) ----------------------- - -news -++++ - - -fixes -+++++ - -- redirection loop occurs when remember-me wasn't checked during login -- fixes issues with git blob history generation -- don't fetch branch for git in file history dropdown. Causes unneeded slowness - - -1.3.0 (**2012-02-26**) ----------------------- - -news -++++ - -- code review, inspired by github code-comments -- #215 rst and markdown README files support -- #252 Container-based and proxy pass-through authentication support -- #44 branch browser. Filtering of changelog by branches -- mercurial bookmarks support -- new hover top menu, optimized to add maximum size for important views -- configurable clone url template with possibility to specify protocol like - ssh:// or http:// and also manually alter other parts of clone_url. -- enabled largefiles extension by default -- optimized summary file pages and saved a lot of unused space in them -- #239 option to manually mark repository as fork -- #320 mapping of commit authors to RhodeCode users -- #304 hashes are displayed using monospace font -- diff configuration, toggle white lines and context lines -- #307 configurable diffs, whitespace toggle, increasing context lines -- sorting on branches, tags and bookmarks using YUI datatable -- improved file filter on files page -- implements #330 api method for listing nodes ar particular revision -- #73 added linking issues in commit messages to chosen issue tracker url - based on user defined regular expression -- added linking of changesets in commit messages -- new compact changelog with expandable commit messages -- firstname and lastname are optional in user creation -- #348 added post-create repository hook -- #212 global encoding settings is now configurable from .ini files -- #227 added repository groups permissions -- markdown gets codehilite extensions -- new API methods, delete_repositories, grante/revoke permissions for groups - and repos - - -fixes -+++++ - -- rewrote dbsession management for atomic operations, and better error handling -- fixed sorting of repo tables -- #326 escape of special html entities in diffs -- normalized user_name => username in api attributes -- fixes #298 ldap created users with mixed case emails created conflicts - on saving a form -- fixes issue when owner of a repo couldn't revoke permissions for users - and groups -- fixes #271 rare JSON serialization problem with statistics -- fixes #337 missing validation check for conflicting names of a group with a - repository group -- #340 fixed session problem for mysql and celery tasks -- fixed #331 RhodeCode mangles repository names if the a repository group - contains the "full path" to the repositories -- #355 RhodeCode doesn't store encrypted LDAP passwords - - -1.2.5 (**2012-01-28**) ----------------------- - -news -++++ - -fixes -+++++ - -- #340 Celery complains about MySQL server gone away, added session cleanup - for celery tasks -- #341 "scanning for repositories in None" log message during Rescan was missing - a parameter -- fixed creating archives with subrepos. Some hooks were triggered during that - operation leading to crash. -- fixed missing email in account page. -- Reverted Mercurial to 2.0.1 for windows due to bug in Mercurial that makes - forking on windows impossible - - -1.2.4 (**2012-01-19**) ----------------------- - -news -++++ - -- RhodeCode is bundled with mercurial series 2.0.X by default, with - full support to largefiles extension. Enabled by default in new installations -- #329 Ability to Add/Remove Groups to/from a Repository via AP -- added requires.txt file with requirements - -fixes -+++++ - -- fixes db session issues with celery when emailing admins -- #331 RhodeCode mangles repository names if the a repository group - contains the "full path" to the repositories -- #298 Conflicting e-mail addresses for LDAP and RhodeCode users -- DB session cleanup after hg protocol operations, fixes issues with - `mysql has gone away` errors -- #333 doc fixes for get_repo api function -- #271 rare JSON serialization problem with statistics enabled -- #337 Fixes issues with validation of repository name conflicting with - a group name. A proper message is now displayed. -- #292 made ldap_dn in user edit readonly, to get rid of confusion that field - doesn't work -- #316 fixes issues with web description in hgrc files - - -1.2.3 (**2011-11-02**) ----------------------- - -news -++++ - -- added option to manage repository group for non admin users -- added following API methods for get_users, create_user, get_users_groups, - get_users_group, create_users_group, add_user_to_users_groups, get_repos, - get_repo, create_repo, add_user_to_repo -- implements #237 added password confirmation for my account - and admin edit user. -- implements #291 email notification for global events are now sent to all - administrator users, and global config email. - -fixes -+++++ - -- added option for passing auth method for smtp mailer -- #276 issue with adding a single user with id>10 to usergroups -- #277 fixes windows LDAP settings in which missing values breaks the ldap auth -- #288 fixes managing of repos in a group for non admin user - - -1.2.2 (**2011-10-17**) ----------------------- - -news -++++ - -- #226 repo groups are available by path instead of numerical id - -fixes -+++++ - -- #259 Groups with the same name but with different parent group -- #260 Put repo in group, then move group to another group -> repo becomes unavailable -- #258 RhodeCode 1.2 assumes egg folder is writable (lockfiles problems) -- #265 ldap save fails sometimes on converting attributes to booleans, - added getter and setter into model that will prevent from this on db model level -- fixed problems with timestamps issues #251 and #213 -- fixes #266 RhodeCode allows to create repo with the same name and in - the same parent as group -- fixes #245 Rescan of the repositories on Windows -- fixes #248 cannot edit repos inside a group on windows -- fixes #219 forking problems on windows - - -1.2.1 (**2011-10-08**) ----------------------- - -news -++++ - - -fixes -+++++ - -- fixed problems with basic auth and push problems -- gui fixes -- fixed logger - - -1.2.0 (**2011-10-07**) ----------------------- - -news -++++ - -- implemented #47 repository groups -- implemented #89 Can setup google analytics code from settings menu -- implemented #91 added nicer looking archive urls with more download options - like tags, branches -- implemented #44 into file browsing, and added follow branch option -- implemented #84 downloads can be enabled/disabled for each repository -- anonymous repository can be cloned without having to pass default:default - into clone url -- fixed #90 whoosh indexer can index chooses repositories passed in command - line -- extended journal with day aggregates and paging -- implemented #107 source code lines highlight ranges -- implemented #93 customizable changelog on combined revision ranges - - equivalent of githubs compare view -- implemented #108 extended and more powerful LDAP configuration -- implemented #56 user groups -- major code rewrites optimized codes for speed and memory usage -- raw and diff downloads are now in git format -- setup command checks for write access to given path -- fixed many issues with international characters and unicode. It uses utf8 - decode with replace to provide less errors even with non utf8 encoded strings -- #125 added API KEY access to feeds -- #109 Repository can be created from external Mercurial link (aka. remote - repository, and manually updated (via pull) from admin panel -- beta git support - push/pull server + basic view for git repos -- added followers page and forks page -- server side file creation (with binary file upload interface) - and edition with commits powered by codemirror -- #111 file browser file finder, quick lookup files on whole file tree -- added quick login sliding menu into main page -- changelog uses lazy loading of affected files details, in some scenarios - this can improve speed of changelog page dramatically especially for - larger repositories. -- implements #214 added support for downloading subrepos in download menu. -- Added basic API for direct operations on rhodecode via JSON -- Implemented advanced hook management - -fixes -+++++ - -- fixed file browser bug, when switching into given form revision the url was - not changing -- fixed propagation to error controller on simplehg and simplegit middlewares -- fixed error when trying to make a download on empty repository -- fixed problem with '[' chars in commit messages in journal -- fixed #99 Unicode errors, on file node paths with non utf-8 characters -- journal fork fixes -- removed issue with space inside renamed repository after deletion -- fixed strange issue on formencode imports -- fixed #126 Deleting repository on Windows, rename used incompatible chars. -- #150 fixes for errors on repositories mapped in db but corrupted in - filesystem -- fixed problem with ascendant characters in realm #181 -- fixed problem with sqlite file based database connection pool -- whoosh indexer and code stats share the same dynamic extensions map -- fixes #188 - relationship delete of repo_to_perm entry on user removal -- fixes issue #189 Trending source files shows "show more" when no more exist -- fixes issue #197 Relative paths for pidlocks -- fixes issue #198 password will require only 3 chars now for login form -- fixes issue #199 wrong redirection for non admin users after creating a repository -- fixes issues #202, bad db constraint made impossible to attach same group - more than one time. Affects only mysql/postgres -- fixes #218 os.kill patch for windows was missing sig param -- improved rendering of dag (they are not trimmed anymore when number of - heads exceeds 5) - - -1.1.8 (**2011-04-12**) ----------------------- - -news -++++ - -- improved windows support - -fixes -+++++ - -- fixed #140 freeze of python dateutil library, since new version is python2.x - incompatible -- setup-app will check for write permission in given path -- cleaned up license info issue #149 -- fixes for issues #137,#116 and problems with unicode and accented characters. -- fixes crashes on gravatar, when passed in email as unicode -- fixed tooltip flickering problems -- fixed came_from redirection on windows -- fixed logging modules, and sql formatters -- windows fixes for os.kill issue #133 -- fixes path splitting for windows issues #148 -- fixed issue #143 wrong import on migration to 1.1.X -- fixed problems with displaying binary files, thanks to Thomas Waldmann -- removed name from archive files since it's breaking ui for long repo names -- fixed issue with archive headers sent to browser, thanks to Thomas Waldmann -- fixed compatibility for 1024px displays, and larger dpi settings, thanks to - Thomas Waldmann -- fixed issue #166 summary pager was skipping 10 revisions on second page - - -1.1.7 (**2011-03-23**) ----------------------- - -news -++++ - -fixes -+++++ - -- fixed (again) #136 installation support for FreeBSD - - -1.1.6 (**2011-03-21**) ----------------------- - -news -++++ - -fixes -+++++ - -- fixed #136 installation support for FreeBSD -- RhodeCode will check for python version during installation - - -1.1.5 (**2011-03-17**) ----------------------- - -news -++++ - -- basic windows support, by exchanging pybcrypt into sha256 for windows only - highly inspired by idea of mantis406 - -fixes -+++++ - -- fixed sorting by author in main page -- fixed crashes with diffs on binary files -- fixed #131 problem with boolean values for LDAP -- fixed #122 mysql problems thanks to striker69 -- fixed problem with errors on calling raw/raw_files/annotate functions - with unknown revisions -- fixed returned rawfiles attachment names with international character -- cleaned out docs, big thanks to Jason Harris - - -1.1.4 (**2011-02-19**) ----------------------- - -news -++++ - -fixes -+++++ - -- fixed formencode import problem on settings page, that caused server crash - when that page was accessed as first after server start -- journal fixes -- fixed option to access repository just by entering http://server/ - - -1.1.3 (**2011-02-16**) ----------------------- - -news -++++ - -- implemented #102 allowing the '.' character in username -- added option to access repository just by entering http://server/ -- celery task ignores result for better performance - -fixes -+++++ - -- fixed ehlo command and non auth mail servers on smtp_lib. Thanks to - apollo13 and Johan Walles -- small fixes in journal -- fixed problems with getting setting for celery from .ini files -- registration, password reset and login boxes share the same title as main - application now -- fixed #113: to high permissions to fork repository -- fixed problem with '[' chars in commit messages in journal -- removed issue with space inside renamed repository after deletion -- db transaction fixes when filesystem repository creation failed -- fixed #106 relation issues on databases different than sqlite -- fixed static files paths links to use of url() method - - -1.1.2 (**2011-01-12**) ----------------------- - -news -++++ - - -fixes -+++++ - -- fixes #98 protection against float division of percentage stats -- fixed graph bug -- forced webhelpers version since it was making troubles during installation - - -1.1.1 (**2011-01-06**) ----------------------- - -news -++++ - -- added force https option into ini files for easier https usage (no need to - set server headers with this options) -- small css updates - -fixes -+++++ - -- fixed #96 redirect loop on files view on repositories without changesets -- fixed #97 unicode string passed into server header in special cases (mod_wsgi) - and server crashed with errors -- fixed large tooltips problems on main page -- fixed #92 whoosh indexer is more error proof - - -1.1.0 (**2010-12-18**) ----------------------- - -news -++++ - -- rewrite of internals for vcs >=0.1.10 -- uses mercurial 1.7 with dotencode disabled for maintaining compatibility - with older clients -- anonymous access, authentication via ldap -- performance upgrade for cached repos list - each repository has its own - cache that's invalidated when needed. -- performance upgrades on repositories with large amount of commits (20K+) -- main page quick filter for filtering repositories -- user dashboards with ability to follow chosen repositories actions -- sends email to admin on new user registration -- added cache/statistics reset options into repository settings -- more detailed action logger (based on hooks) with pushed changesets lists - and options to disable those hooks from admin panel -- introduced new enhanced changelog for merges that shows more accurate results -- new improved and faster code stats (based on pygments lexers mapping tables, - showing up to 10 trending sources for each repository. Additionally stats - can be disabled in repository settings. -- gui optimizations, fixed application width to 1024px -- added cut off (for large files/changesets) limit into config files -- whoosh, celeryd, upgrade moved to paster command -- other than sqlite database backends can be used - -fixes -+++++ - -- fixes #61 forked repo was showing only after cache expired -- fixes #76 no confirmation on user deletes -- fixes #66 Name field misspelled -- fixes #72 block user removal when he owns repositories -- fixes #69 added password confirmation fields -- fixes #87 RhodeCode crashes occasionally on updating repository owner -- fixes #82 broken annotations on files with more than 1 blank line at the end -- a lot of fixes and tweaks for file browser -- fixed detached session issues -- fixed when user had no repos he would see all repos listed in my account -- fixed ui() instance bug when global hgrc settings was loaded for server - instance and all hgrc options were merged with our db ui() object -- numerous small bugfixes - -(special thanks for TkSoh for detailed feedback) - - -1.0.2 (**2010-11-12**) ----------------------- - -news -++++ - -- tested under python2.7 -- bumped sqlalchemy and celery versions - -fixes -+++++ - -- fixed #59 missing graph.js -- fixed repo_size crash when repository had broken symlinks -- fixed python2.5 crashes. - - -1.0.1 (**2010-11-10**) ----------------------- - -news -++++ - -- small css updated - -fixes -+++++ - -- fixed #53 python2.5 incompatible enumerate calls -- fixed #52 disable mercurial extension for web -- fixed #51 deleting repositories don't delete it's dependent objects - - -1.0.0 (**2010-11-02**) ----------------------- - -news -++++ - - -fixes -+++++ -- security bugfix simplehg wasn't checking for permissions on commands - other than pull or push. -- fixed doubled messages after push or pull in admin journal -- templating and css corrections, fixed repo switcher on chrome, updated titles -- admin menu accessible from options menu on repository view -- permissions cached queries - - -1.0.0rc4 (**2010-10-12**) --------------------------- - -news -++++ - - -fixes -+++++ -- fixed python2.5 missing simplejson imports (thanks to Jens Bäckman) -- removed cache_manager settings from sqlalchemy meta -- added sqlalchemy cache settings to ini files -- validated password length and added second try of failure on paster setup-app -- fixed setup database destroy prompt even when there was no db - - -1.0.0rc3 (**2010-10-11**) -------------------------- - -news -++++ - - -fixes -+++++ - -- fixed i18n during installation. - - -1.0.0rc2 (**2010-10-11**) -------------------------- - -news -++++ - - -fixes -+++++ - -- Disabled dirsize in file browser, it's causing nasty bug when dir renames - occure. After vcs is fixed it'll be put back again. -- templating/css rewrites, optimized css. +.. _logs: https://kallithea-scm.org/repos/kallithea/changelog diff --git a/docs/conf.py b/docs/conf.py --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# RhodeCode documentation build configuration file, created by +# Kallithea documentation build configuration file, created by # sphinx-quickstart on Sun Oct 10 16:46:37 2010. # # This file is execfile()d with the current directory set to its containing dir. @@ -44,8 +44,8 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'RhodeCode' -copyright = u'%s, Marcin Kuzminski' % (datetime.datetime.now().year) +project = u'Kallithea' +copyright = u'2010-2014 by various authors, licensed as GPLv3.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -54,7 +54,7 @@ copyright = u'%s, Marcin Kuzminski' % (d # The short X.Y version. root = os.path.dirname(os.path.dirname(__file__)) sys.path.append(root) -from rhodecode import __version__ +from kallithea import __version__ version = __version__ # The full version, including alpha/beta/rc tags. release = __version__ @@ -171,7 +171,7 @@ html_theme_path = ['theme'] #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'RhodeCodedoc' +htmlhelp_basename = 'Kallithea-docs' # -- Options for LaTeX output -------------------------------------------------- @@ -185,7 +185,7 @@ htmlhelp_basename = 'RhodeCodedoc' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'RhodeCode.tex', u'RhodeCode Documentation', + ('index', 'Kallithea.tex', u'Kallithea Documentation', u'Marcin Kuzminski', 'manual'), ] @@ -218,7 +218,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'rhodecode', u'RhodeCode Documentation', + ('index', 'kallithea', u'Kallithea Documentation', [u'Marcin Kuzminski'], 1) ] diff --git a/docs/contributing.rst b/docs/contributing.rst --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -1,26 +1,26 @@ .. _contributing: ========================= -Contributing to RhodeCode +Contributing to Kallithea ========================= -If you would like to contribute to RhodeCode, please contact me, any help is +If you would like to contribute to Kallithea, please contact us, any help is greatly appreciated! Could I request that you make your source contributions by first forking the -RhodeCode repository on bitbucket_ -https://bitbucket.org/marcinkuzminski/rhodecode and then make your changes to +Kallithea repository on bitbucket_ +https://bitbucket.org/conservancy/kallithea and then make your changes to your forked repository. Please post all fixes into **dev** bookmark since your change might be already fixed there and i try to merge all fixes from dev into stable, and not the other way. Finally, when you are finished with your changes, -please send me a pull request. +please send us a pull request. -To run RhodeCode in a development version you always need to install the latest -required libs. Simply clone rhodecode and switch to beta branch:: +To run Kallithea in a development version you always need to install the latest +required libs. Simply clone Kallithea and switch to beta branch:: - hg clone -u dev https://secure.rhodecode.org/rhodecode + hg clone https://kallithea-scm.org/repos/kallithea -after downloading/pulling RhodeCode make sure you run:: +after downloading/pulling Kallithea make sure you run:: python setup.py develop @@ -41,13 +41,11 @@ to change your testing enviroment. There's a special set of tests for push/pull operations, you can runn them using:: paster serve test.ini --pid-file=test.pid --daemon - RC_WHOOSH_TEST_DISABLE=1 RC_NO_TMP_PATH=1 nosetests -x rhodecode/tests/other/test_vcs_operations.py + KALLITHEA_WHOOSH_TEST_DISABLE=1 KALLITHEA_NO_TMP_PATH=1 nosetests -x kallithea/tests/other/test_vcs_operations.py kill -9 $(cat test.pid) | Thank you for any contributions! -| Marcin - .. _bitbucket: http://bitbucket.org/ diff --git a/docs/index.rst b/docs/index.rst --- a/docs/index.rst +++ b/docs/index.rst @@ -11,6 +11,7 @@ Users Guide :maxdepth: 1 installation + installation_win setup upgrade diff --git a/docs/installation.rst b/docs/installation.rst --- a/docs/installation.rst +++ b/docs/installation.rst @@ -4,28 +4,28 @@ Installation ============ -``RhodeCode`` is written entirely in Python. Before posting any issues make +``Kallithea`` is written entirely in Python. Before posting any issues make sure, your not missing any system libraries and using right version of -libraries required by RhodeCode. There's also restriction in terms of mercurial -clients. Minimal version of hg client known working fine with RhodeCode is +libraries required by Kallithea. There's also restriction in terms of mercurial +clients. Minimal version of hg client known working fine with Kallithea is **1.6**. If you're using older client, please upgrade. -Installing RhodeCode from PyPI (aka "Cheeseshop") +Installing Kallithea from PyPI (aka "Cheeseshop") ------------------------------------------------- -Rhodecode requires python version 2.5 or higher. +Kallithea requires python version 2.5 or higher. -The easiest way to install ``rhodecode`` is to run:: +The easiest way to install ``kallithea`` is to run:: - easy_install rhodecode + easy_install kallithea Or:: - pip install rhodecode + pip install kallithea -If you prefer to install RhodeCode manually simply grab latest release from -http://pypi.python.org/pypi/RhodeCode, decompress the archive and run:: +If you prefer to install Kallithea manually simply grab latest release from +http://pypi.python.org/pypi/Kallithea, decompress the archive and run:: python setup.py install @@ -39,8 +39,8 @@ Step by step installation example for Li ------------------------------------------- -For installing RhodeCode i highly recommend using separate virtualenv_. This -way many required by RhodeCode libraries will remain sandboxed from your main +For installing Kallithea i highly recommend using separate virtualenv_. This +way many required by Kallithea libraries will remain sandboxed from your main python and making things less problematic when doing system python updates. Alternative very detailed installation instructions for Ubuntu Server with @@ -50,64 +50,64 @@ celery, indexer and daemon scripts: http - Assuming you have installed virtualenv_ create a new virtual environment using virtualenv command:: - virtualenv --no-site-packages /opt/rhodecode-venv + virtualenv --no-site-packages /opt/kallithea-venv .. note:: Using ``--no-site-packages`` when generating your virtualenv is **very important**. This flag provides the necessary isolation for running the set of packages required by - RhodeCode. If you do not specify ``--no-site-packages``, - it's possible that RhodeCode will not install properly into + Kallithea. If you do not specify ``--no-site-packages``, + it's possible that Kallithea will not install properly into the virtualenv, or, even if it does, may not run properly, depending on the packages you've already got installed into your Python's "main" site-packages dir. -- this will install new virtualenv_ into `/opt/rhodecode-venv`. +- this will install new virtualenv_ into `/opt/kallithea-venv`. - Activate the virtualenv_ by running:: - source /opt/rhodecode-venv/bin/activate + source /opt/kallithea-venv/bin/activate .. note:: If you're using UNIX, *do not* use ``sudo`` to run the ``virtualenv`` script. It's perfectly acceptable (and desirable) to create a virtualenv as a normal user. -- Make a folder for rhodecode data files, and configuration somewhere on the +- Make a folder for Kallithea data files, and configuration somewhere on the filesystem. For example:: - mkdir /opt/rhodecode + mkdir /opt/kallithea -- Go into the created directory run this command to install rhodecode:: +- Go into the created directory run this command to install kallithea:: - easy_install rhodecode + easy_install kallithea or:: - pip install rhodecode + pip install kallithea -- This will install rhodecode together with pylons and all other required +- This will install Kallithea together with pylons and all other required python libraries into activated virtualenv Requirements for Celery (optional) ---------------------------------- In order to gain maximum performance -there are some third-party you must install. When RhodeCode is used +there are some third-party you must install. When Kallithea is used together with celery you have to install some kind of message broker, recommended one is rabbitmq_ to make the async tasks work. -Of course RhodeCode works in sync mode also and then you do not have to install +Of course Kallithea works in sync mode also and then you do not have to install any third party applications. However, using Celery_ will give you a large speed improvement when using many big repositories. If you plan to use -RhodeCode for say 7 to 10 repositories, RhodeCode will perform perfectly well +Kallithea for say 7 to 10 repositories, Kallithea will perform perfectly well without celery running. -If you make the decision to run RhodeCode with celery make sure you run +If you make the decision to run Kallithea with celery make sure you run celeryd using paster and message broker together with the application. .. note:: - Installing message broker and using celery is optional, RhodeCode will + Installing message broker and using celery is optional, Kallithea will work perfectly fine without them. diff --git a/docs/installation_win.rst b/docs/installation_win.rst --- a/docs/installation_win.rst +++ b/docs/installation_win.rst @@ -5,7 +5,7 @@ Step by step Installation for Windows ===================================== -RhodeCode step-by-step install Guide for Windows +Kallithea step-by-step install Guide for Windows Target OS: Windows XP SP3 32bit English (Clean installation) + All Windows Updates until 24-may-2012 @@ -121,22 +121,22 @@ that came preinstalled in Vista/7 and ca Typically: C:\\Python27 -Step5 - RhodeCode folder structure +Step5 - Kallithea folder structure ---------------------------------- -Create a RhodeCode folder structure +Create a Kallithea folder structure -This is only a example to install RhodeCode, you can of course change +This is only a example to install Kallithea, you can of course change it. However, this guide will follow the proposed structure, so please later adapt the paths if you change them. My recommendation is to use folders with NO SPACES. But you can try if you are brave... Create the following folder structure:: - C:\RhodeCode - C:\RhodeCode\Bin - C:\RhodeCode\Env - C:\RhodeCode\Repos + C:\Kallithea + C:\Kallithea\Bin + C:\Kallithea\Env + C:\Kallithea\Repos Step6 - Install virtualenv @@ -146,24 +146,24 @@ Install Virtual Env for Python Navigate to: http://www.virtualenv.org/en/latest/index.html#installation Right click on "virtualenv.py" file and choose "Save link as...". -Download to C:\\RhodeCode (or whatever you want) +Download to C:\\Kallithea (or whatever you want) (the file is located at https://raw.github.com/pypa/virtualenv/master/virtualenv.py) -Create a virtual Python environment in C:\\RhodeCode\\Env (or similar). To +Create a virtual Python environment in C:\\Kallithea\\Env (or similar). To do so, open a CMD (Python Path should be included in Step3), navigate where you downloaded "virtualenv.py", and write:: - python virtualenv.py C:\RhodeCode\Env + python virtualenv.py C:\Kallithea\Env (--no-site-packages is now the default behaviour of virtualenv, no need to include it) -Step7 - Install RhodeCode +Step7 - Install Kallithea ------------------------- -Finally, install RhodeCode +Finally, install Kallithea Close previously opened command prompt/s, and open a Visual Studio 2008 Command Prompt (**IMPORTANT!!**). To do so, go to Start Menu, and then open @@ -186,31 +186,31 @@ to:: In that CMD (loaded with VS2008 PATHs) type:: - cd C:\RhodeCode\Env\Scripts (or similar) + cd C:\Kallithea\Env\Scripts (or similar) activate -The prompt will change into "(Env) C:\\RhodeCode\\Env\\Scripts" or similar +The prompt will change into "(Env) C:\\Kallithea\\Env\\Scripts" or similar (depending of your folder structure). Then type:: - pip install rhodecode + pip install kallithea (long step, please wait until fully complete) Some warnings will appear, don't worry as they are normal. -Step8 - Configuring RhodeCode +Step8 - Configuring Kallithea ----------------------------- -steps taken from http://packages.python.org/RhodeCode/setup.html +steps taken from http://packages.python.org/Kallithea/setup.html You have to use the same Visual Studio 2008 command prompt as Step7, so if you closed it reopen it following the same commands (including the "activate" one). When ready, just type:: - cd C:\RhodeCode\Bin - paster make-config RhodeCode production.ini + cd C:\Kallithea\Bin + paster make-config Kallithea production.ini Then, you must edit production.ini to fit your needs (ip address, ip port, mail settings, database, whatever). I recommend using NotePad++ @@ -221,14 +221,14 @@ character differences between Unix and W For the sake of simplicity lets run it with the default settings. After your edits (if any), in the previous Command Prompt, type:: - paster setup-rhodecode production.ini + paster setup-db production.ini (this time a NEW database will be installed, you must follow a different -step to later UPGRADE to a newer RhodeCode version) +step to later UPGRADE to a newer Kallithea version) The script will ask you for confirmation about creating a NEW database, answer yes (y) -The script will ask you for repository path, answer C:\\RhodeCode\\Repos +The script will ask you for repository path, answer C:\\Kallithea\\Repos (or similar) The script will ask you for admin username and password, answer "admin" + "123456" (or whatever you want) @@ -239,11 +239,11 @@ If you make some mistake and the script it again. -Step9 - Running RhodeCode +Step9 - Running Kallithea ------------------------- -In the previous command prompt, being in the C:\\RhodeCode\\Bin folder, +In the previous command prompt, being in the C:\\Kallithea\\Bin folder, just type:: paster serve production.ini @@ -261,7 +261,7 @@ again. Don't forget the "http://" in Int What this Guide does not cover: - Installing Celery -- Running RhodeCode as Windows Service. You can investigate here: +- Running Kallithea as Windows Service. You can investigate here: - http://pypi.python.org/pypi/wsgisvc - http://ryrobes.com/python/running-python-scripts-as-a-windows-service/ @@ -275,18 +275,18 @@ What this Guide does not cover: Upgrading ========= -Stop running RhodeCode +Stop running Kallithea Open a CommandPrompt like in Step7 (VS2008 path + activate) and type:: - easy_install -U rhodecode - cd \RhodeCode\Bin + easy_install -U kallithea + cd \Kallithea\Bin { backup your production.ini file now} :: - paster make-config RhodeCode production.ini + paster make-config Kallithea production.ini (check changes and update your production.ini accordingly) :: paster upgrade-db production.ini (update database) -Full steps in http://packages.python.org/RhodeCode/upgrade.html +Full steps in http://packages.python.org/Kallithea/upgrade.html diff --git a/docs/make.bat b/docs/make.bat --- a/docs/make.bat +++ b/docs/make.bat @@ -88,9 +88,9 @@ if "%1" == "qthelp" ( echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\RhodeCode.qhcp + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Kallithea.qhcp echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\RhodeCode.ghc + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Kallithea.ghc goto end ) diff --git a/docs/setup.rst b/docs/setup.rst --- a/docs/setup.rst +++ b/docs/setup.rst @@ -5,66 +5,66 @@ Setup ===== -Setting up RhodeCode +Setting up Kallithea -------------------- -First, you will need to create a RhodeCode configuration file. Run the +First, you will need to create a Kallithea configuration file. Run the following command to do this:: - paster make-config RhodeCode production.ini + paster make-config Kallithea production.ini - This will create the file `production.ini` in the current directory. This - configuration file contains the various settings for RhodeCode, e.g proxy + configuration file contains the various settings for Kallithea, e.g proxy port, email settings, usage of static files, cache, celery settings and logging. -Next, you need to create the databases used by RhodeCode. I recommend that you +Next, you need to create the databases used by Kallithea. I recommend that you use postgresql or sqlite (default). If you choose a database other than the default ensure you properly adjust the db url in your production.ini -configuration file to use this other database. RhodeCode currently supports +configuration file to use this other database. Kallithea currently supports postgresql, sqlite and mysql databases. Create the database by running the following command:: - paster setup-rhodecode production.ini + paster setup-db production.ini This will prompt you for a "root" path. This "root" path is the location where -RhodeCode will store all of its repositories on the current machine. After -entering this "root" path ``setup-rhodecode`` will also prompt you for a username -and password for the initial admin account which ``setup-rhodecode`` sets +Kallithea will store all of its repositories on the current machine. After +entering this "root" path ``setup-db`` will also prompt you for a username +and password for the initial admin account which ``setup-db`` sets up for you. setup process can be fully automated, example for lazy:: - paster setup-rhodecode production.ini --user=marcink --password=secret --email=marcin@rhodecode.org --repos=/home/marcink/my_repos + paster setup-db production.ini --user=nn --password=secret --email=nn@your.kallithea.server --repos=/home/nn/my_repos -- The ``setup-rhodecode`` command will create all of the needed tables and an +- The ``setup-db`` command will create all of the needed tables and an admin account. When choosing a root path you can either use a new empty location, or a location which already contains existing repositories. If you - choose a location which contains existing repositories RhodeCode will simply + choose a location which contains existing repositories Kallithea will simply add all of the repositories at the chosen location to it's database. (Note: make sure you specify the correct path to the root). - Note: the given path for mercurial_ repositories **must** be write accessible - for the application. It's very important since the RhodeCode web interface + for the application. It's very important since the Kallithea web interface will work without write access, but when trying to do a push it will eventually fail with permission denied errors unless it has write access. -You are now ready to use RhodeCode, to run it simply execute:: +You are now ready to use Kallithea, to run it simply execute:: paster serve production.ini -- This command runs the RhodeCode server. The web app should be available at the +- This command runs the Kallithea server. The web app should be available at the 127.0.0.1:5000. This ip and port is configurable via the production.ini file created in previous step -- Use the admin account you created above when running ``setup-rhodecode`` +- Use the admin account you created above when running ``setup-db`` to login to the web app. - The default permissions on each repository is read, and the owner is admin. Remember to update these if needed. - In the admin panel you can toggle ldap, anonymous, permissions settings. As well as edit more advanced options on users and repositories -Optionally users can create `rcextensions` package that extends RhodeCode +Optionally users can create `rcextensions` package that extends Kallithea functionality. To do this simply execute:: paster make-rcext production.ini @@ -77,36 +77,36 @@ Please see the `__init__.py` file inside for more details. -Using RhodeCode with SSH +Using Kallithea with SSH ------------------------ -RhodeCode currently only hosts repositories using http and https. (The addition +Kallithea currently only hosts repositories using http and https. (The addition of ssh hosting is a planned future feature.) However you can easily use ssh in -parallel with RhodeCode. (Repository access via ssh is a standard "out of +parallel with Kallithea. (Repository access via ssh is a standard "out of the box" feature of mercurial_ and you can use this to access any of the -repositories that RhodeCode is hosting. See PublishingRepositories_) +repositories that Kallithea is hosting. See PublishingRepositories_) -RhodeCode repository structures are kept in directories with the same name +Kallithea repository structures are kept in directories with the same name as the project. When using repository groups, each group is a subdirectory. This allows you to easily use ssh for accessing repositories. In order to use ssh you need to make sure that your web-server and the users login accounts have the correct permissions set on the appropriate directories. (Note that these permissions are independent of any permissions you have set up -using the RhodeCode web interface.) +using the Kallithea web interface.) -If your main directory (the same as set in RhodeCode settings) is for example -set to **/home/hg** and the repository you are using is named `rhodecode`, then +If your main directory (the same as set in Kallithea settings) is for example +set to **/home/hg** and the repository you are using is named `kallithea`, then to clone via ssh you should run:: - hg clone ssh://user@server.com/home/hg/rhodecode + hg clone ssh://user@server.com/home/hg/kallithea Using other external tools such as mercurial-server_ or using ssh key based authentication is fully supported. Note: In an advanced setup, in order for your ssh access to use the same -permissions as set up via the RhodeCode web interface, you can create an -authentication hook to connect to the rhodecode db and runs check functions for +permissions as set up via the Kallithea web interface, you can create an +authentication hook to connect to the Kallithea db and runs check functions for permissions against that. Setting up Whoosh full text search @@ -116,7 +116,7 @@ Starting from version 1.1 the whoosh ind command ``make-index``. To use ``make-index`` you must specify the configuration file that stores the location of the index. You may specify the location of the repositories (`--repo-location`). If not specified, this value is retrieved -from the RhodeCode database. This was required prior to 1.2. Starting from +from the Kallithea database. This was required prior to 1.2. Starting from version 1.2 it is also possible to specify a comma separated list of repositories (`--index-only`) to build index only on chooses repositories skipping any other found in repos location @@ -135,14 +135,14 @@ For a full index rebuild use:: building index just for chosen repositories is possible with such command:: - paster make-index production.ini --index-only=vcs,rhodecode + paster make-index production.ini --index-only=vcs,kallithea In order to do periodical index builds and keep your index always up to date. It's recommended to do a crontab entry for incremental indexing. An example entry might look like this:: - /path/to/python/bin/paster make-index /path/to/rhodecode/production.ini + /path/to/python/bin/paster make-index /path/to/kallithea/production.ini When using incremental mode (the default) whoosh will check the last modification date of each file and add it to be reindexed if a newer file is @@ -156,7 +156,7 @@ or in the admin panel you can check `bui Setting up LDAP support ----------------------- -RhodeCode starting from version 1.1 supports ldap authentication. In order +Kallithea starting from version 1.1 supports ldap authentication. In order to use LDAP, you have to install the python-ldap_ package. This package is available via pypi, so you can install it by running @@ -314,7 +314,7 @@ LDAP Search Scope : required Login Attribute : required The LDAP record attribute that will be matched as the USERNAME or - ACCOUNT used to connect to RhodeCode. This will be added to `LDAP + ACCOUNT used to connect to Kallithea. This will be added to `LDAP Filter`_ for locating the User object. If `LDAP Filter`_ is specified as "LDAPFILTER", `Login Attribute`_ is specified as "uid" and the user has connected as "jsmith" then the `LDAP Filter`_ will be augmented as below @@ -338,19 +338,19 @@ Email Attribute : required The LDAP record attribute which represents the user's email address. If all data are entered correctly, and python-ldap_ is properly installed -users should be granted access to RhodeCode with ldap accounts. At this -time user information is copied from LDAP into the RhodeCode user database. +users should be granted access to Kallithea with ldap accounts. At this +time user information is copied from LDAP into the Kallithea user database. This means that updates of an LDAP user object may not be reflected as a -user update in RhodeCode. +user update in Kallithea. If You have problems with LDAP access and believe You entered correct -information check out the RhodeCode logs, any error messages sent from LDAP +information check out the Kallithea logs, any error messages sent from LDAP will be saved there. Active Directory '''''''''''''''' -RhodeCode can use Microsoft Active Directory for user authentication. This +Kallithea can use Microsoft Active Directory for user authentication. This is done through an LDAP or LDAPS connection to Active Directory. The following LDAP configuration settings are typical for using Active Directory :: @@ -368,32 +368,32 @@ appropriately configured. Authentication by container or reverse-proxy -------------------------------------------- -Starting with version 1.3, RhodeCode supports delegating the authentication +Starting with version 1.3, Kallithea supports delegating the authentication of users to its WSGI container, or to a reverse-proxy server through which all clients access the application. -When these authentication methods are enabled in RhodeCode, it uses the +When these authentication methods are enabled in Kallithea, it uses the username that the container/proxy (Apache/Nginx/etc) authenticated and doesn't perform the authentication itself. The authorization, however, is still done by -RhodeCode according to its settings. +Kallithea according to its settings. When a user logs in for the first time using these authentication methods, -a matching user account is created in RhodeCode with default permissions. An -administrator can then modify it using RhodeCode's admin interface. +a matching user account is created in Kallithea with default permissions. An +administrator can then modify it using Kallithea's admin interface. It's also possible for an administrator to create accounts and configure their permissions before the user logs in for the first time. Container-based authentication '''''''''''''''''''''''''''''' -In a container-based authentication setup, RhodeCode reads the user name from +In a container-based authentication setup, Kallithea reads the user name from the ``REMOTE_USER`` server variable provided by the WSGI container. After setting up your container (see `Apache's WSGI config`_), you'd need to configure it to require authentication on the location configured for -RhodeCode. +Kallithea. -In order for RhodeCode to start using the provided username, you should set the +In order for Kallithea to start using the provided username, you should set the following in the [app:main] section of your .ini file:: container_auth_enabled = true @@ -402,7 +402,7 @@ following in the [app:main] section of y Proxy pass-through authentication ''''''''''''''''''''''''''''''''' -In a proxy pass-through authentication setup, RhodeCode reads the user name +In a proxy pass-through authentication setup, Kallithea reads the user name from the ``X-Forwarded-User`` request header, which should be configured to be sent by the reverse-proxy server. @@ -420,8 +420,8 @@ reverse-proxy setup with basic auth:: SetEnvIf X-Url-Scheme https HTTPS=1 AuthType Basic - AuthName "RhodeCode authentication" - AuthUserFile /home/web/rhodecode/.htpasswd + AuthName "Kallithea authentication" + AuthUserFile /home/web/kallithea/.htpasswd require valid-user RequestHeader unset X-Forwarded-User @@ -432,7 +432,7 @@ reverse-proxy setup with basic auth:: RequestHeader set X-Forwarded-User %{RU}e -In order for RhodeCode to start using the forwarded username, you should set +In order for Kallithea to start using the forwarded username, you should set the following in the [app:main] section of your .ini file:: proxypass_auth_enabled = true @@ -446,7 +446,7 @@ the following in the [app:main] section Integration with Issue trackers ------------------------------- -RhodeCode provides a simple integration with issue trackers. It's possible +Kallithea provides a simple integration with issue trackers. It's possible to define a regular expression that will fetch issue id stored in commit messages and replace that with an url to this issue. To enable this simply uncomment following variables in the ini file:: @@ -477,24 +477,24 @@ There are 4 built in hooks that cannot b checkboxes on previos section). To add another custom hook simply fill in first section with . and the second one with hook path. Example hooks -can be found at *rhodecode.lib.hooks*. +can be found at *kallithea.lib.hooks*. Changing default encoding ------------------------- -By default RhodeCode uses utf8 encoding, starting from 1.3 series this +By default Kallithea uses utf8 encoding, starting from 1.3 series this can be changed, simply edit default_encoding in .ini file to desired one. -This affects many parts in rhodecode including committers names, filenames, -encoding of commit messages. In addition RhodeCode can detect if `chardet` -library is installed. If `chardet` is detected RhodeCode will fallback to it +This affects many parts in Kallithea including committers names, filenames, +encoding of commit messages. In addition Kallithea can detect if `chardet` +library is installed. If `chardet` is detected Kallithea will fallback to it when there are encode/decode errors. Setting Up Celery ----------------- -Since version 1.1 celery is configured by the rhodecode ini configuration files. +Since version 1.1 celery is configured by the Kallithea ini configuration files. Simply set use_celery=true in the ini file then add / change the configuration variables inside the ini file. @@ -509,14 +509,14 @@ In order to start using celery run:: .. note:: Make sure you run this command from the same virtualenv, and with the same - user that rhodecode runs. + user that Kallithea runs. HTTPS support ------------- There are two ways to enable https: -- Set HTTP_X_URL_SCHEME in your http server headers, than rhodecode will +- Set HTTP_X_URL_SCHEME in your http server headers, than Kallithea will recognize this headers and make proper https redirections - Alternatively, change the `force_https = true` flag in the ini configuration to force using https, no headers are needed than to enable https @@ -542,8 +542,8 @@ Sample config for nginx using proxy:: error_log /var/log/nginx/gist.error.log; ssl on; - ssl_certificate gist.rhodecode.myserver.com.crt; - ssl_certificate_key gist.rhodecode.myserver.com.key; + ssl_certificate gist.your.kallithea.server.crt; + ssl_certificate_key gist.your.kallithea.server.key; ssl_session_timeout 5m; @@ -551,19 +551,19 @@ Sample config for nginx using proxy:: ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5; ssl_prefer_server_ciphers on; - rewrite ^/(.+)$ https://rhodecode.myserver.com/_admin/gists/$1; - rewrite (.*) https://rhodecode.myserver.com/_admin/gists; + rewrite ^/(.+)$ https://your.kallithea.server/_admin/gists/$1; + rewrite (.*) https://your.kallithea.server/_admin/gists; } server { listen 443; - server_name rhodecode.myserver.com; - access_log /var/log/nginx/rhodecode.access.log; - error_log /var/log/nginx/rhodecode.error.log; + server_name your.kallithea.server; + access_log /var/log/nginx/kallithea.access.log; + error_log /var/log/nginx/kallithea.error.log; ssl on; - ssl_certificate rhodecode.myserver.com.crt; - ssl_certificate_key rhodecode.myserver.com.key; + ssl_certificate your.kallithea.server.crt; + ssl_certificate_key your.kallithea.server.key; ssl_session_timeout 5m; @@ -573,7 +573,7 @@ Sample config for nginx using proxy:: ## uncomment root directive if you want to serve static files by nginx ## requires static_files = false in .ini file - #root /path/to/installation/rhodecode/public; + #root /path/to/installation/kallithea/public; include /etc/nginx/proxy.conf; location / { try_files $uri @rhode; @@ -626,7 +626,7 @@ Here is a sample configuration file for #Directive to properly generate url (clone url) for pylons ProxyPreserveHost On - #rhodecode instance + #kallithea instance ProxyPass / http://127.0.0.1:5000/ ProxyPassReverse / http://127.0.0.1:5000/ @@ -668,7 +668,7 @@ then change into your chose Apache's WSGI config -------------------- -Alternatively, RhodeCode can be set up with Apache under mod_wsgi. For +Alternatively, Kallithea can be set up with Apache under mod_wsgi. For that, you'll need to: - Install mod_wsgi. If using a Debian-based distro, you can install @@ -681,7 +681,7 @@ that, you'll need to: a2enmod wsgi - Create a wsgi dispatch script, like the one below. Make sure you - check the paths correctly point to where you installed RhodeCode + check the paths correctly point to where you installed Kallithea and its Python Virtual Environment. - Enable the WSGIScriptAlias directive for the wsgi dispatch script, as in the following example. Once again, check the paths are @@ -691,8 +691,8 @@ Here is a sample excerpt from an Apache WSGIDaemonProcess pylons \ threads=4 \ - python-path=/home/web/rhodecode/pyenv/lib/python2.6/site-packages - WSGIScriptAlias / /home/web/rhodecode/dispatch.wsgi + python-path=/home/web/kallithea/pyenv/lib/python2.6/site-packages + WSGIScriptAlias / /home/web/kallithea/dispatch.wsgi WSGIPassAuthorization On .. note:: @@ -700,7 +700,7 @@ Here is a sample excerpt from an Apache into above configuration .. note:: - Running RhodeCode in multiprocess mode in apache is not supported, + Running Kallithea in multiprocess mode in apache is not supported, make sure you don't specify `processes=num` directive in the config @@ -708,22 +708,22 @@ Example wsgi dispatch script:: import os os.environ["HGENCODING"] = "UTF-8" - os.environ['PYTHON_EGG_CACHE'] = '/home/web/rhodecode/.egg-cache' + os.environ['PYTHON_EGG_CACHE'] = '/home/web/kallithea/.egg-cache' # sometimes it's needed to set the curent dir - os.chdir('/home/web/rhodecode/') + os.chdir('/home/web/kallithea/') import site - site.addsitedir("/home/web/rhodecode/pyenv/lib/python2.6/site-packages") + site.addsitedir("/home/web/kallithea/pyenv/lib/python2.6/site-packages") from paste.deploy import loadapp from paste.script.util.logging_config import fileConfig - fileConfig('/home/web/rhodecode/production.ini') - application = loadapp('config:/home/web/rhodecode/production.ini') + fileConfig('/home/web/kallithea/production.ini') + application = loadapp('config:/home/web/kallithea/production.ini') Note: when using mod_wsgi you'll need to install the same version of -Mercurial that's inside RhodeCode's virtualenv also on the system's Python +Mercurial that's inside Kallithea's virtualenv also on the system's Python environment. @@ -732,7 +732,7 @@ Other configuration files Some example init.d scripts can be found in init.d directory:: - https://secure.rhodecode.org/rhodecode/files/beta/init.d + https://kallithea-scm.org/repos/kallithea/files/tip/init.d/ .. _virtualenv: http://pypi.python.org/pypi/virtualenv .. _python: http://www.python.org/ @@ -742,5 +742,4 @@ Some example init.d scripts can be found .. _python-ldap: http://www.python-ldap.org/ .. _mercurial-server: http://www.lshift.net/mercurial-server.html .. _PublishingRepositories: http://mercurial.selenic.com/wiki/PublishingRepositories -.. _Issues tracker: https://bitbucket.org/marcinkuzminski/rhodecode/issues -.. _google group rhodecode: http://groups.google.com/group/rhodecode +.. _Issues tracker: https://bitbucket.org/conservancy/kallithea/issues diff --git a/docs/theme/nature/layout.html b/docs/theme/nature/layout.html --- a/docs/theme/nature/layout.html +++ b/docs/theme/nature/layout.html @@ -1,17 +1,16 @@ {% extends "basic/layout.html" %} {% block sidebarlogo %} -

Support RhodeCode development.

+

Support Kallithea development

-
- - - - -
+
+ + + + +
diff --git a/docs/theme/nature/static/nature.css_t b/docs/theme/nature/static/nature.css_t --- a/docs/theme/nature/static/nature.css_t +++ b/docs/theme/nature/static/nature.css_t @@ -54,7 +54,7 @@ div.footer a { } div.related { - background-color: #003367; + background-color: #577632; line-height: 32px; color: #fff; text-shadow: 0px 1px 0 #444; diff --git a/docs/upgrade.rst b/docs/upgrade.rst --- a/docs/upgrade.rst +++ b/docs/upgrade.rst @@ -12,16 +12,16 @@ Upgrading from PyPI (aka "Cheeseshop") configuration backup before doing an upgrade. (These directions will use '{version}' to note that this is the version of - Rhodecode that these files were used with. If backing up your RhodeCode + Kallithea that these files were used with. If backing up your Kallithea instance from version 1.3.6 to 1.4.0, the ``production.ini`` file would be backed up to ``production.ini.1-3-6``.) -If using a sqlite database, stop the Rhodecode process/daemon/service, and +If using a sqlite database, stop the Kallithea process/daemon/service, and then make a copy of the database file:: - service rhodecode stop - cp rhodecode.db rhodecode.db.{version} + service kallithea stop + cp kallithea.db kallithea.db.{version} Back up your configuration file:: @@ -30,30 +30,30 @@ Back up your configuration file:: Ensure that you are using the Python Virtual Environment that you'd originally -installed Rhodecode in:: +installed Kallithea in:: pip freeze -will list all packages installed in the current environment. If Rhodecode +will list all packages installed in the current environment. If Kallithea isn't listed, change virtual environments to your venv location:: - source /opt/rhodecode-venv/bin/activate + source /opt/kallithea-venv/bin/activate -Once you have verified the environment you can upgrade ``Rhodecode`` with:: +Once you have verified the environment you can upgrade ``Kallithea`` with:: - easy_install -U rhodecode + easy_install -U kallithea Or:: - pip install --upgrade rhodecode + pip install --upgrade kallithea Then run the following command from the installation directory:: - paster make-config RhodeCode production.ini + paster make-config Kallithea production.ini -This will display any changes made by the new version of RhodeCode to your +This will display any changes made by the new version of Kallithea to your current configuration. It will try to perform an automerge. It's recommended that you re-check the content after the automerge. @@ -80,21 +80,21 @@ options that need to be set. DB schema upgrade library has some limitations and can sometimes fail if you try to upgrade from older major releases. In such case simply run upgrades sequentially, eg. upgrading from 1.2.X to 1.5.X should be done like that: 1.2.X. > 1.3.X > 1.4.X > 1.5.X - You can always specify what version of RhodeCode you want to install for example in pip - `pip install RhodeCode==1.3.6` + You can always specify what version of Kallithea you want to install for example in pip + `pip install Kallithea==1.3.6` You may find it helpful to clear out your log file so that new errors are readily apparent:: - echo > rhodecode.log + echo > kallithea.log -Once that is complete, you may now start your upgraded Rhodecode Instance:: +Once that is complete, you may now start your upgraded Kallithea Instance:: - service rhodecode start + service kallithea start Or:: - paster serve /var/www/rhodecode/production.ini + paster serve /var/www/kallithea/production.ini .. note:: If you're using Celery, make sure you restart all instances of it after diff --git a/docs/usage/backup.rst b/docs/usage/backup.rst --- a/docs/usage/backup.rst +++ b/docs/usage/backup.rst @@ -1,26 +1,26 @@ .. _backup: ==================== -Backing up RhodeCode +Backing up Kallithea ==================== Settings -------- -Just copy your .ini file, it contains all RhodeCode settings. +Just copy your .ini file, it contains all Kallithea settings. Whoosh index ------------ Whoosh index is located in **/data/index** directory where you installed -RhodeCode ie. the same place where the ini file is located +Kallithea ie. the same place where the ini file is located Database -------- -When using sqlite just copy rhodecode.db. +When using sqlite just copy kallithea.db. Any other database engine requires a manual backup operation. Database backup will contain all gathered statistics diff --git a/docs/usage/debugging.rst b/docs/usage/debugging.rst --- a/docs/usage/debugging.rst +++ b/docs/usage/debugging.rst @@ -1,10 +1,10 @@ .. _debugging: =================== -Debugging RhodeCode +Debugging Kallithea =================== -If you encountered problems with RhodeCode here are some instructions how to +If you encountered problems with Kallithea here are some instructions how to possibly debug them. ** First make sure you're using the latest version available.** @@ -12,7 +12,7 @@ possibly debug them. enable detailed debug --------------------- -RhodeCode uses standard python logging modules to log it's output. +Kallithea uses standard python logging modules to log it's output. By default only loggers with INFO level are displayed. To enable full output change `level = DEBUG` for all logging handlers in currently used .ini file. This change will allow to see much more detailed output in the logfile or diff --git a/docs/usage/general.rst b/docs/usage/general.rst --- a/docs/usage/general.rst +++ b/docs/usage/general.rst @@ -1,17 +1,17 @@ .. _general: ======================= -General RhodeCode usage +General Kallithea usage ======================= Repository deleting ------------------- -Currently when admin/owner deletes a repository, RhodeCode does not physically +Currently when admin/owner deletes a repository, Kallithea does not physically delete a repository from filesystem, it renames it in a special way so it's not possible to push,clone or access repository. It's worth a notice that, -even if someone will be given administrative access to RhodeCode and will +even if someone will be given administrative access to Kallithea and will delete a repository You can easy restore such action by restoring `rm__` from the repository name, and internal repository storage (.hg/.git). There is also a special command for cleaning such archived repos:: @@ -60,7 +60,7 @@ example:: This can be an issue for build systems and any other hardcoded scripts, moving repository to a group leads to a need for changing external systems. To -overcome this RhodeCode introduces a non changable replacement url. It's +overcome this Kallithea introduces a non changable replacement url. It's simply an repository ID prefixed with `_` above urls are also accessible as:: http://server.com/_ @@ -74,13 +74,13 @@ Mailing ------- When administrator will fill up the mailing settings in .ini files -RhodeCode will send mails on user registration, or when RhodeCode errors occur +Kallithea will send mails on user registration, or when Kallithea errors occur on errors the mails will have a detailed traceback of error. Mails are also sent for code comments. If someone comments on a changeset mail is sent to all participants, the person who commited the changeset -(if present in RhodeCode), and to all people mentioned with @mention system. +(if present in Kallithea), and to all people mentioned with @mention system. Trending source files @@ -89,13 +89,13 @@ Trending source files Trending source files are calculated based on pre defined dict of known types and extensions. If You miss some extension or Would like to scan some custom files it's possible to add new types in `LANGUAGES_EXTENSIONS_MAP` dict -located in `/rhodecode/lib/celerylib/tasks.py` +located in `/kallithea/lib/celerylib/tasks.py` Cloning remote repositories --------------------------- -RhodeCode has an ability to clone remote repos from given remote locations. +Kallithea has an ability to clone remote repos from given remote locations. Currently it support following options: - hg -> hg clone @@ -109,9 +109,9 @@ Currently it support following options: If you need to clone repositories that are protected via basic auth, you might pass the url with stored credentials inside eg. -`http://user:passw@remote.server/repo`, RhodeCode will try to login and clone +`http://user:passw@remote.server/repo`, Kallithea will try to login and clone using given credentials. Please take a note that they will be stored as -plaintext inside the database. RhodeCode will remove auth info when showing the +plaintext inside the database. Kallithea will remove auth info when showing the clone url in summary page. @@ -120,7 +120,7 @@ Visual settings in admin pannel ------------------------------- -Visualisation settings in RhodeCode settings view are extra customizations +Visualisation settings in Kallithea settings view are extra customizations of server behavior. There are 3 main section in the settings. General @@ -133,7 +133,7 @@ define company specific information into key that would add give info about a manager of each repository. There's no limit for adding custom fields. Newly created fields are accessible via API. -`Show RhodeCode version` option toggles displaying exact RhodeCode version in +`Show Kallithea version` option toggles displaying exact Kallithea version in the footer @@ -153,7 +153,7 @@ public/private icons should be shown in Meta-Tagging ~~~~~~~~~~~~ -With this option enabled, special metatags that are recognisible by RhodeCode +With this option enabled, special metatags that are recognisible by Kallithea will be turned into colored tags. Currently available tags are:: [featured] diff --git a/docs/usage/git_support.rst b/docs/usage/git_support.rst --- a/docs/usage/git_support.rst +++ b/docs/usage/git_support.rst @@ -5,18 +5,18 @@ GIT support =========== -Git support in RhodeCode 1.3 was enabled by default. You need to have a git +Git support in Kallithea 1.3 was enabled by default. You need to have a git client installed on the machine to make git fully work. Although There is one limitation on git usage. - large pushes requires a http server with chunked encoding support. -if you plan to use git you need to run RhodeCode with some +if you plan to use git you need to run Kallithea with some http server that supports chunked encoding which git http protocol uses, i recommend using waitress_ or gunicorn_ (linux only) for `paste` wsgi app replacement. Starting from version 1.4 waitress_ is the default wsgi server -used in RhodeCode. +used in Kallithea. To use, simply change change the following in the .ini file:: @@ -42,7 +42,7 @@ You can simply run `paster serve` as usu You can always disable git/hg support by editing a -file **rhodecode/__init__.py** and commenting out backends +file **kallithea/__init__.py** and commenting out backends .. code-block:: python diff --git a/docs/usage/locking.rst b/docs/usage/locking.rst --- a/docs/usage/locking.rst +++ b/docs/usage/locking.rst @@ -1,7 +1,7 @@ .. _locking: =================================== -RhodeCode repository locking system +Kallithea repository locking system =================================== @@ -20,7 +20,7 @@ influence this state: user has write/admin permissions on this repo -RhodeCode will remember the user id who locked the repo +Kallithea will remember the user id who locked the repo only this specific user can unlock the repo (locked=false) by calling - `hg/git push ` diff --git a/docs/usage/performance.rst b/docs/usage/performance.rst --- a/docs/usage/performance.rst +++ b/docs/usage/performance.rst @@ -1,15 +1,15 @@ .. _performance: ================================ -Optimizing RhodeCode Performance +Optimizing Kallithea Performance ================================ -When serving large amount of big repositories RhodeCode can start +When serving large amount of big repositories Kallithea can start performing slower than expected. Because of demanding nature of handling large amount of data from version control systems here are some tips how to get the best performance. -* RhodeCode will perform better on machines with faster disks (SSD/SAN). It's +* Kallithea will perform better on machines with faster disks (SSD/SAN). It's more important to have faster disk than faster CPU. * Slowness on initial page can be easily fixed by grouping repositories, and/or @@ -17,7 +17,7 @@ the best performance. option and vcs_full_cache setting in .ini file -Follow these few steps to improve performance of RhodeCode system. +Follow these few steps to improve performance of Kallithea system. 1. Increase cache @@ -30,7 +30,7 @@ Follow these few steps to improve perfor few hundreds of repositories on main page can sometimes make the system to behave slow when cache expires for all of them. Increasing `expire` option to day (86400) or a week (604800) will improve general response - times for the main page. RhodeCode has an intelligent cache expiration + times for the main page. Kallithea has an intelligent cache expiration system and it will expire cache for repositories that had been changed. 2. Switch from sqlite to postgres or mysql @@ -40,10 +40,10 @@ Follow these few steps to improve perfor setup. Switching to mysql or postgres will result in a immediate performance increase. -3. Scale RhodeCode horizontally +3. Scale Kallithea horizontally Scaling horizontally can give huge performance increase when dealing with - large traffic (large amount of users, CI servers etc). RhodeCode can be + large traffic (large amount of users, CI servers etc). Kallithea can be scaled horizontally on one (recommended) or multiple machines. In order to scale horizontally you need to do the following: @@ -53,7 +53,7 @@ Follow these few steps to improve perfor dir contains template caches, sessions, whoosh index and it's used for tasks locking (so it's safe across multiple instances). Set the `cache_dir`, `index_dir`, `beaker.cache.data_dir`, `beaker.cache.lock_dir` - variables in each .ini file to shared location across RhodeCode instances + variables in each .ini file to shared location across Kallithea instances - if celery is used each instance should run separate celery instance, but the message broken should be common to all of them (ex one rabbitmq shared server) diff --git a/docs/usage/statistics.rst b/docs/usage/statistics.rst --- a/docs/usage/statistics.rst +++ b/docs/usage/statistics.rst @@ -4,9 +4,9 @@ Statistics ========== -The RhodeCode statistics system makes heavy demands of the server resources, so +The Kallithea statistics system makes heavy demands of the server resources, so in order to keep a balance between usability and performance, the statistics are -cached inside db and are gathered incrementally, this is how RhodeCode does +cached inside db and are gathered incrementally, this is how Kallithea does this: With Celery disabled @@ -16,14 +16,14 @@ With Celery disabled updates statistics cache. - This happens on each single visit to the statistics page until all commits are fetched. Statistics are kept cached until additional commits are added to the - repository. In such a case RhodeCode will only fetch the new commits when + repository. In such a case Kallithea will only fetch the new commits when updating it's cache. With Celery enabled ------------------- -- On the first visit to the summary page RhodeCode will create tasks that will +- On the first visit to the summary page Kallithea will create tasks that will execute on celery workers. This task will gather all of the stats until all commits are parsed, each task will parse 250 commits, and run the next task to parse next 250 commits, until all of the commits are parsed. diff --git a/docs/usage/subrepos.rst b/docs/usage/subrepos.rst --- a/docs/usage/subrepos.rst +++ b/docs/usage/subrepos.rst @@ -1,10 +1,10 @@ .. _subrepos: ============================================= -working with RhodeCode and mercurial subrepos +working with Kallithea and mercurial subrepos ============================================= -example usage of Subrepos with RhodeCode:: +example usage of Subrepos with Kallithea:: ## init a simple repo hg init repo1 @@ -16,7 +16,7 @@ example usage of Subrepos with RhodeCode #clone subrepo we want to add hg clone http://rc.local/subrepo - ## use path like url to existing repo in RhodeCode + ## use path like url to existing repo in Kallithea echo "subrepo = http://rc.local/subrepo" > .hgsub hg add .hgsub @@ -26,11 +26,11 @@ example usage of Subrepos with RhodeCode In file list of repo1 you will see a connected subrepo at revision it was during cloning. -Clicking in subrepos link should send you to proper repository in RhodeCode +Clicking in subrepos link should send you to proper repository in Kallithea cloning repo1 will also clone attached subrepository. -Next we can edit the subrepo data, and push back to RhodeCode. This will update +Next we can edit the subrepo data, and push back to Kallithea. This will update both of repositories. see http://mercurial.aragost.com/kick-start/en/subrepositories/ for more diff --git a/docs/usage/troubleshooting.rst b/docs/usage/troubleshooting.rst --- a/docs/usage/troubleshooting.rst +++ b/docs/usage/troubleshooting.rst @@ -9,19 +9,19 @@ Troubleshooting :A: Make sure either to set the `static_files = true` in the .ini file or double check the root path for your http setup. It should point to for example: - /home/my-virtual-python/lib/python2.6/site-packages/rhodecode/public + /home/my-virtual-python/lib/python2.6/site-packages/kallithea/public | :Q: **Can't install celery/rabbitmq?** -:A: Don't worry RhodeCode works without them too. No extra setup is required. +:A: Don't worry Kallithea works without them too. No extra setup is required. Try out great celery docs for further help. | :Q: **Long lasting push timeouts?** :A: Make sure you set a longer timeouts in your proxy/fcgi settings, timeouts - are caused by https server and not RhodeCode. + are caused by https server and not Kallithea. | @@ -43,16 +43,16 @@ Troubleshooting | -:Q: **How i use hooks in RhodeCode?** +:Q: **How i use hooks in Kallithea?** :A: It's easy if they are python hooks just use advanced link in hooks section in Admin panel, that works only for Mercurial. If you want to use githooks, just install proper one in repository eg. create file in - `/gitrepo/hooks/pre-receive`. You can also use RhodeCode-extensions to + `/gitrepo/hooks/pre-receive`. You can also use Kallithea-extensions to connect to callback hooks, for both Git and Mercurial. | -:Q: **RhodeCode is slow for me, how can i make it faster?** +:Q: **Kallithea is slow for me, how can i make it faster?** :A: See the :ref:`performance` section | @@ -67,9 +67,6 @@ Troubleshooting you have installed latest windows patches (especially KB2789397) -For further questions search the `Issues tracker`_, or post a message in the -`google group rhodecode`_ - .. _virtualenv: http://pypi.python.org/pypi/virtualenv .. _python: http://www.python.org/ .. _mercurial: http://mercurial.selenic.com/ @@ -78,5 +75,4 @@ For further questions search the `Issues .. _python-ldap: http://www.python-ldap.org/ .. _mercurial-server: http://www.lshift.net/mercurial-server.html .. _PublishingRepositories: http://mercurial.selenic.com/wiki/PublishingRepositories -.. _Issues tracker: https://bitbucket.org/marcinkuzminski/rhodecode/issues -.. _google group rhodecode: http://groups.google.com/group/rhodecode +.. _Issues tracker: https://bitbucket.org/conservancy/kallithea/issues diff --git a/init.d/celeryd-upstart.conf b/init.d/celeryd-upstart.conf --- a/init.d/celeryd-upstart.conf +++ b/init.d/celeryd-upstart.conf @@ -1,19 +1,19 @@ -# celeryd - run the celeryd daemon as an upstart job for rhodecode +# celeryd - run the celeryd daemon as an upstart job for kallithea # Change variables/paths as necessary and place file /etc/init/celeryd.conf # start/stop/restart as normal upstart job (ie: $ start celeryd) -description "Celery for RhodeCode Mercurial Server" +description "Celery for Kallithea Mercurial Server" author "Matt Zuba - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,10 +11,25 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.__init__ +~~~~~~~~~~~~~~~~~~ + +Kallithea, a web based repository management based on pylons +versioning implementation: http://www.python.org/dev/peps/pep-0386/ + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 9, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, (C) 2014 Bradley M. Kuhn, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import sys import platform -VERSION = (1, 7, 1) +VERSION = (0,) BACKENDS = { 'hg': 'Mercurial repository', 'git': 'Git repository', @@ -41,22 +44,52 @@ CONFIG = {} # Linked module for extensions EXTENSIONS = {} +# BRAND controls internal references in database and config to the products +# own name. +# +# NOTE: If you want compatibility with a database that was originally created +# for use with the RhodeCode software product, change BRAND to "rhodecode", +# either by editing here or by creating a new file: +# echo "BRAND = 'rhodecode'" > kallithea/brand.py + +BRAND = "kallithea" try: - from rhodecode.lib import get_current_revision + from kallithea.brand import BRAND +except ImportError: + pass + +# Prefix for the ui and settings table names +DB_PREFIX = (BRAND + "_") if BRAND != "kallithea" else "" + +# Users.extern_type and .extern_name value for local users +EXTERN_TYPE_INTERNAL = BRAND if BRAND != 'kallithea' else 'internal' + +# db_migrate_version.repository_id value, same as kallithea/lib/dbmigrate/migrate.cfg +DB_MIGRATIONS = BRAND + "_db_migrations" + +try: + from kallithea.lib import get_current_revision _rev = get_current_revision(quiet=True) if _rev and len(VERSION) > 3: VERSION += ('%s' % _rev[0],) except ImportError: pass -__version__ = ('.'.join((str(each) for each in VERSION[:3])) + - '.'.join(VERSION[3:])) -__dbversion__ = 14 # defines current db version for migrations +__version__ = ('.'.join((str(each) for each in VERSION[:3]))) +__dbversion__ = 31 # defines current db version for migrations __platform__ = platform.system() __license__ = 'GPLv3' __py_version__ = sys.version_info -__author__ = 'Marcin Kuzminski' -__url__ = 'http://rhodecode.org' +__author__ = "Various Authors" +__url__ = 'https://kallithea-scm.org/' is_windows = __platform__ in ['Windows'] is_unix = not is_windows + +if len(VERSION) > 3: + __version__ += '.'+VERSION[3] + + if len(VERSION) > 4: + __version__ += VERSION[4] + else: + __version__ += '0' diff --git a/rhodecode/bin/__init__.py b/kallithea/bin/__init__.py rename from rhodecode/bin/__init__.py rename to kallithea/bin/__init__.py --- a/rhodecode/bin/__init__.py +++ b/kallithea/bin/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.bin.__init__ +~~~~~~~~~~~~~~~~~~~~~~ + +Binary scripts for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jun 03, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" diff --git a/rhodecode/bin/base.py b/kallithea/bin/base.py rename from rhodecode/bin/base.py rename to kallithea/bin/base.py --- a/rhodecode/bin/base.py +++ b/kallithea/bin/base.py @@ -1,6 +1,30 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . """ +kallithea.bin.base +~~~~~~~~~~~~~~~~~~ + Base utils for shell scripts + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: May 09, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. """ + import os import sys import random @@ -8,21 +32,21 @@ import urllib2 import pprint try: - from rhodecode.lib.ext_json import json + from kallithea.lib.ext_json import json except ImportError: try: import simplejson as json except ImportError: import json -CONFIG_NAME = '.rhodecode' +CONFIG_NAME = '.config/kallithea' FORMAT_PRETTY = 'pretty' FORMAT_JSON = 'json' def api_call(apikey, apihost, method=None, **kw): """ - Api_call wrapper for RhodeCode. + Api_call wrapper for Kallithea. :param apikey: :param apihost: @@ -46,7 +70,7 @@ def api_call(apikey, apihost, method=Non if not method: raise Exception('please specify method name !') - + apihost = apihost.rstrip('/') id_ = random.randrange(1, 9999) req = urllib2.Request('%s/_admin/api' % apihost, data=json.dumps(_build_data(id_)), @@ -67,7 +91,7 @@ def api_call(apikey, apihost, method=Non class RcConf(object): """ - RhodeCode config for API + Kallithea config for API conf = RcConf() conf['key'] diff --git a/rhodecode/bin/rhodecode_api.py b/kallithea/bin/kallithea_api.py old mode 100755 new mode 100644 rename from rhodecode/bin/rhodecode_api.py rename to kallithea/bin/kallithea_api.py --- a/rhodecode/bin/rhodecode_api.py +++ b/kallithea/bin/kallithea_api.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.bin.api - ~~~~~~~~~~~~~~~~~ - - Api CLI client for RhodeCode - - :created_on: Jun 3, 2012 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,23 +11,36 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.bin.api +~~~~~~~~~~~~~~~~~ + +Api CLI client for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jun 3, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" from __future__ import with_statement import sys import argparse -from rhodecode.bin.base import json, api_call, RcConf, FORMAT_JSON, FORMAT_PRETTY +from kallithea.bin.base import json, api_call, RcConf, FORMAT_JSON, FORMAT_PRETTY def argparser(argv): usage = ( - "rhodecode-api [-h] [--format=FORMAT] [--apikey=APIKEY] [--apihost=APIHOST] " + "kallithea-api [-h] [--format=FORMAT] [--apikey=APIKEY] [--apihost=APIHOST] " "[--config=CONFIG] [--save-config] " "METHOD ...\n" - "Create config file: rhodecode-gist --apikey= --apihost=http://rhodecode.server --save-config" + "Create config file: kallithea-api --apikey= --apihost=http://your.kallithea.server --save-config" ) - parser = argparse.ArgumentParser(description='RhodeCode API cli', + parser = argparse.ArgumentParser(description='Kallithea API cli', usage=usage) ## config @@ -106,15 +108,18 @@ def main(argv=None): print 'Calling method %s => %s' % (method, apihost) json_resp = api_call(apikey, apihost, method, **margs) + error_prefix = '' if json_resp['error']: + error_prefix = 'ERROR:' json_data = json_resp['error'] else: json_data = json_resp['result'] if args.format == FORMAT_JSON: print json.dumps(json_data) elif args.format == FORMAT_PRETTY: - print 'Server response \n%s' % ( - json.dumps(json_data, indent=4, sort_keys=True)) + print 'Server response \n%s%s' % ( + error_prefix, json.dumps(json_data, indent=4, sort_keys=True) + ) return 0 if __name__ == '__main__': diff --git a/rhodecode/bin/rhodecode_backup.py b/kallithea/bin/kallithea_backup.py old mode 100755 new mode 100644 rename from rhodecode/bin/rhodecode_backup.py rename to kallithea/bin/kallithea_backup.py --- a/rhodecode/bin/rhodecode_backup.py +++ b/kallithea/bin/kallithea_backup.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.bin.backup_manager - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Repositories backup manager, it allows to backups all - repositories and send it to backup server using RSA key via ssh. - - :created_on: Feb 28, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.bin.backup_manager +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Repositories backup manager, it allows to backups all +repositories and send it to backup server using RSA key via ssh. + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Feb 28, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import os import sys @@ -39,7 +41,7 @@ logging.basicConfig(level=logging.DEBUG, class BackupManager(object): def __init__(self, repos_location, rsa_key, backup_server): today = datetime.datetime.now().weekday() + 1 - self.backup_file_name = "rhodecode_repos.%s.tar.gz" % today + self.backup_file_name = "repos.%s.tar.gz" % today self.id_rsa_path = self.get_id_rsa(rsa_key) self.repos_path = self.get_repos_path(repos_location) diff --git a/rhodecode/bin/rhodecode_config.py b/kallithea/bin/kallithea_config.py old mode 100644 new mode 100755 rename from rhodecode/bin/rhodecode_config.py rename to kallithea/bin/kallithea_config.py --- a/rhodecode/bin/rhodecode_config.py +++ b/kallithea/bin/kallithea_config.py @@ -1,7 +1,31 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . """ -config generator +kallithea.bin.kallithea_config +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +configuration generator for Kallithea +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jun 18, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. """ + + from __future__ import with_statement import os import sys @@ -13,14 +37,14 @@ here = os.path.dirname(os.path.abspath(_ def argparser(argv): usage = ( - "rhodecode-config [-h] [--filename=FILENAME] [--template=TEMPLATE] \n" + "kallithea-config [-h] [--filename=FILENAME] [--template=TEMPLATE] \n" "VARS optional specify extra template variable that will be available in " "template. Use comma separated key=val format eg.\n" "key1=val1,port=5000,host=127.0.0.1,elements='a\,b\,c'\n" ) parser = argparse.ArgumentParser( - description='RhodeCode CONFIG generator with variable replacement', + description='Kallithea CONFIG generator with variable replacement', usage=usage ) @@ -77,7 +101,7 @@ def _run(argv): 'database_engine': 'sqlite', 'host': '127.0.0.1', 'port': 5000, - 'error_aggregation_service': None + 'error_aggregation_service': None, } if other: # parse arguments, we assume only first is correct diff --git a/rhodecode/bin/rhodecode_gist.py b/kallithea/bin/kallithea_gist.py old mode 100755 new mode 100644 rename from rhodecode/bin/rhodecode_gist.py rename to kallithea/bin/kallithea_gist.py --- a/rhodecode/bin/rhodecode_gist.py +++ b/kallithea/bin/kallithea_gist.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.bin.gist - ~~~~~~~~~~~~~~~~~~ - - Gist CLI client for RhodeCode - - :created_on: May 9, 2013 - :author: marcink - :copyright: (C) 2010-2013 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.bin.kallithea_gist +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Gist CLI client for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: May 9, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" from __future__ import with_statement import os @@ -30,25 +32,25 @@ import stat import argparse import fileinput -from rhodecode.bin.base import json, api_call, RcConf, FORMAT_JSON, FORMAT_PRETTY +from kallithea.bin.base import json, api_call, RcConf, FORMAT_JSON, FORMAT_PRETTY def argparser(argv): usage = ( - "rhodecode-gist [-h] [--format=FORMAT] [--apikey=APIKEY] [--apihost=APIHOST] " + "kallithea-gist [-h] [--format=FORMAT] [--apikey=APIKEY] [--apihost=APIHOST] " "[--config=CONFIG] [--save-config] [GIST OPTIONS] " "[filename or stdin use - for terminal stdin ]\n" - "Create config file: rhodecode-gist --apikey= --apihost=http://rhodecode.server --save-config" + "Create config file: kallithea-gist --apikey= --apihost=http://your.kallithea.server --save-config" ) - parser = argparse.ArgumentParser(description='RhodeCode Gist cli', + parser = argparse.ArgumentParser(description='Kallithea Gist cli', usage=usage) ## config group = parser.add_argument_group('config') group.add_argument('--apikey', help='api access key') group.add_argument('--apihost', help='api host') - group.add_argument('--config', help='config file path DEFAULT: ~/.rhodecode') + group.add_argument('--config', help='config file path DEFAULT: ~/.config/kallithea') group.add_argument('--save-config', action='store_true', help='save the given config into a file') diff --git a/rhodecode/bin/ldap_sync.conf b/kallithea/bin/ldap_sync.conf rename from rhodecode/bin/ldap_sync.conf rename to kallithea/bin/ldap_sync.conf --- a/rhodecode/bin/ldap_sync.conf +++ b/kallithea/bin/ldap_sync.conf @@ -1,10 +1,10 @@ [default] -api_url = http://your.rhodecode.server:5000/_admin/api +api_url = http://your.kallithea.server:5000/_admin/api api_user = admin api_key = XXXXXXXXXXXX ldap_uri = ldap://your.ldap.server:389 -ldap_user = cn=rhodecode,ou=binders,dc=linaro,dc=org +ldap_user = cn=kallithea,ou=binders,dc=linaro,dc=org ldap_key = XXXXXXXXX base_dn = dc=linaro,dc=org diff --git a/rhodecode/bin/ldap_sync.py b/kallithea/bin/ldap_sync.py old mode 100644 new mode 100755 rename from rhodecode/bin/ldap_sync.py rename to kallithea/bin/ldap_sync.py --- a/rhodecode/bin/ldap_sync.py +++ b/kallithea/bin/ldap_sync.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -10,13 +11,26 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.bin.__init__ +~~~~~~~~~~~~~~~~~~~~~~ + +LDAP sync script + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Mar 06, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import ldap import urllib2 import uuid try: - from rhodecode.lib.compat import json + from kallithea.lib.compat import json except ImportError: try: import simplejson as json @@ -33,7 +47,7 @@ class InvalidResponseIDError(Exception): """ Request and response don't have the same UUID. """ -class RhodecodeResponseError(Exception): +class ResponseError(Exception): """ Response has an error, something went wrong with request execution. """ @@ -45,7 +59,7 @@ class UserNotInGroupError(Exception): """ User is not a member of the target group. """ -class RhodecodeAPI(): +class API(object): def __init__(self, url, key): self.url = url @@ -60,8 +74,8 @@ class RhodecodeAPI(): "args": args } - def rhodecode_api_post(self, method, args): - """Send a generic API post to Rhodecode. + def post(self, method, args): + """Send a generic API post to Kallithea. This will generate the UUID for validation check after the response is returned. Handle errors and get the result back. @@ -80,17 +94,17 @@ class RhodecodeAPI(): raise InvalidResponseIDError("UUID does not match.") if response["error"] is not None: - raise RhodecodeResponseError(response["error"]) + raise ResponseError(response["error"]) return response["result"] def create_group(self, name, active=True): - """Create the Rhodecode user group.""" + """Create the Kallithea user group.""" args = { "group_name": name, "active": str(active) } - self.rhodecode_api_post("create_users_group", args) + self.post("create_user_group", args) def add_membership(self, group, username): """Add specific user to a group.""" @@ -98,7 +112,7 @@ class RhodecodeAPI(): "usersgroupid": group, "userid": username } - result = self.rhodecode_api_post("add_user_to_users_group", args) + result = self.post("add_user_to_user_group", args) if not result["success"]: raise UserAlreadyInGroupError("User %s already in group %s." % (username, group)) @@ -109,7 +123,7 @@ class RhodecodeAPI(): "usersgroupid": group, "userid": username } - result = self.rhodecode_api_post("remove_user_from_users_group", args) + result = self.post("remove_user_from_user_group", args) if not result["success"]: raise UserNotInGroupError("User %s not in group %s." % (username, group)) @@ -117,7 +131,7 @@ class RhodecodeAPI(): def get_group_members(self, name): """Get the list of member usernames from a user group.""" args = {"usersgroupid": name} - members = self.rhodecode_api_post("get_users_group", args)['members'] + members = self.post("get_user_group", args)['members'] member_list = [] for member in members: member_list.append(member["username"]) @@ -126,15 +140,15 @@ class RhodecodeAPI(): def get_group(self, name): """Return group info.""" args = {"usersgroupid": name} - return self.rhodecode_api_post("get_users_group", args) + return self.post("get_user_group", args) def get_user(self, username): """Return user info.""" args = {"userid": username} - return self.rhodecode_api_post("get_user", args) + return self.post("get_user", args) -class LdapClient(): +class LdapClient(object): def __init__(self, uri, user, key, base_dn): self.client = ldap.initialize(uri, trace_level=0) @@ -190,16 +204,16 @@ class LdapSync(object): config.get("default", "ldap_user"), config.get("default", "ldap_key"), config.get("default", "base_dn")) - self.rhodocode_api = RhodecodeAPI(config.get("default", "api_url"), + self.rhodocode_api = API(config.get("default", "api_url"), config.get("default", "api_key")) def update_groups_from_ldap(self): - """Add all the groups from LDAP to Rhodecode.""" + """Add all the groups from LDAP to Kallithea.""" added = existing = 0 groups = self.ldap_client.get_groups() for group in groups: try: - self.rhodecode_api.create_group(group) + self.kallithea_api.create_repo_group(group) added += 1 except Exception: existing += 1 @@ -207,25 +221,25 @@ class LdapSync(object): return added, existing def update_memberships_from_ldap(self, group): - """Update memberships in rhodecode based on the LDAP groups.""" + """Update memberships based on the LDAP groups.""" groups = self.ldap_client.get_groups() group_users = self.ldap_client.get_group_users(groups, group) # Delete memberships first from each group which are not part # of the group any more. - rhodecode_members = self.rhodecode_api.get_group_members(group) - for rhodecode_member in rhodecode_members: - if rhodecode_member not in group_users: + members = self.kallithea_api.get_group_members(group) + for member in members: + if member not in group_users: try: self.rhodocode_api.remove_membership(group, - rhodecode_member) + member) except UserNotInGroupError: pass # Add memberships. for member in group_users: try: - self.rhodecode_api.add_membership(group, member) + self.kallithea_api.add_membership(group, member) except UserAlreadyInGroupError: # TODO: handle somehow maybe.. pass @@ -240,5 +254,5 @@ if __name__ == '__main__': # How should we handle this.. Either sync users as well at this step, # or just ignore those who don't exist. If we want the second case, # we need to find a way to recognize the right exception (we always get - # RhodecodeResponseError with no error code so maybe by return msg (?) + # ResponseError with no error code so maybe by return msg (?) sync.update_memberships_from_ldap(gr) diff --git a/kallithea/bin/rebranddb.py b/kallithea/bin/rebranddb.py new file mode 100755 --- /dev/null +++ b/kallithea/bin/rebranddb.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +Script for rebranding of database to and from what Kallithea expects + +Works on databases from v1.7.2 to v2.2.5 +""" + +import os +import sys +from sqlalchemy import * +import sqlalchemy.orm +import sqlalchemy.ext.declarative +import migrate.changeset # a part of sqlalchemy-migrate which is available on pypi + +def do_migrate(db, old, new): + print 'Migrating %s from %s to %s' % (db, old or '?', new) + metadata = MetaData() + metadata.bind = create_engine(db) + metadata.reflect() + assert metadata.tables, 'Cannot reflect table names from db' + + if not old: + assert 'db_migrate_version' in metadata.tables, 'Cannot reflect db_migrate_version from db' + t = metadata.tables['db_migrate_version'] + l = t.select().where(t.c.repository_path == 'versions').execute().fetchall() + assert len(l) == 1, 'Cannot find a single versions entry in db_migrate_version' + assert l[0].repository_id.endswith('_db_migrations') + old = l[0].repository_id[:-len('_db_migrations')] + print 'Detected migration from old name %s' % old + if new != old: + assert not t.select().where(t.c.repository_id == new + '_db_migrations').execute().fetchall(), 'db_migrate_version has entries for both old and new name' + + def tablename(brand, s): + return s if brand == 'kallithea' else (brand + '_' + s) + new_ui_name = tablename(new, 'ui') + old_ui_name = tablename(old, 'ui') + new_settings_name = tablename(new, 'settings') + old_settings_name = tablename(old, 'settings') + + # Table renames using sqlalchemy-migrate (available on pypi) + if new_ui_name == old_ui_name: + print 'No renaming of %s' % new_ui_name + else: + try: + t = metadata.tables[old_ui_name] + print 'Renaming', t, 'to', new_ui_name + migrate.changeset.rename_table(t, new_ui_name) + except KeyError, e: + print 'Not renaming ui:', e + + if new_settings_name == old_settings_name: + print 'No renaming of %s' % new_settings_name + else: + try: + t = metadata.tables[old_settings_name] + print 'Renaming', t, 'to', new_settings_name + migrate.changeset.rename_table(t, new_settings_name) + except KeyError, e: + print 'Not renaming settings:', e + + # using this API because ... dunno ... it is simple and works + conn = metadata.bind.connect() + trans = conn.begin() + t = metadata.tables['users'] + + print 'Bulk fixing of User extern_name' + try: + t.c.extern_name + except AttributeError: + print 'No extern_name to rename' + else: + t.update().where(t.c.extern_name == old).values(extern_name=new).execute() + + print 'Bulk fixing of User extern_type' + try: + t.c.extern_type + except AttributeError: + print 'No extern_type to rename' + else: + t.update().where(t.c.extern_type == old).values(extern_type=new).execute() + + trans.commit() + + # For the following conversions, use ORM ... and create stub models that works for that purpose + Base = sqlalchemy.ext.declarative.declarative_base() + + class Ui(Base): + __tablename__ = new_ui_name + ui_id = Column("ui_id", Integer(), primary_key=True) + ui_section = Column("ui_section", String()) + ui_key = Column("ui_key", String()) + ui_value = Column("ui_value", String()) + ui_active = Column("ui_active", Boolean()) + + class Setting(Base): + __tablename__ = new_settings_name + app_settings_id = Column("app_settings_id", Integer(), primary_key=True) + app_settings_name = Column("app_settings_name", String()) + app_settings_value = Column("app_settings_value", String()) + #app_settings_type = Column("app_settings_type", String()) # not present in v1.7.2 + + class DbMigrateVersion(Base): + __tablename__ = 'db_migrate_version' + repository_id = Column('repository_id', String(), primary_key=True) + repository_path = Column('repository_path', Text) + version = Column('version', Integer) + + Session = sqlalchemy.orm.sessionmaker(bind=metadata.bind) + session = Session() + + print 'Fixing hook names' + + oldhooks = u'python:%s.lib.hooks.' % old + newhooks = u'python:%s.lib.hooks.' % new + for u in session.query(Ui).filter(Ui.ui_section == 'hooks').all(): + if u.ui_value.startswith(oldhooks): + print '- fixing %s' % u.ui_key + u.ui_value = newhooks + u.ui_value[len(oldhooks):] + session.add(u) + session.commit() + + print 'Fixing auth module names' + old_auth_name = 'internal' if old == 'kallithea' else old + new_auth_name = 'internal' if new == 'kallithea' else new + for s in session.query(Setting).filter(Setting.app_settings_name == 'auth_plugins').all(): + print '- fixing %s' % s.app_settings_name + s.app_settings_value = (s.app_settings_value + .replace(old + '.lib.auth_modules.auth_', new + '.lib.auth_modules.auth_') + .replace('.auth_modules.auth_' + old_auth_name, '.auth_modules.auth_' + new_auth_name)) + session.add(s) + for s in session.query(Setting).filter(Setting.app_settings_name == 'auth_' + old_auth_name + '_enabled').all(): + print '- fixing %s' % s.app_settings_name + s.app_settings_name = 'auth_' + new_auth_name + '_enabled' + session.add(s) + session.commit() + + print 'Fixing db migration version number' + for s in session.query(DbMigrateVersion).filter(DbMigrateVersion.repository_id == old + '_db_migrations', DbMigrateVersion.repository_path == 'versions').all(): + print '- fixing %s' % s.repository_id + s.repository_id = new + '_db_migrations' + session.commit() + + print 'Done' + +def main(argv): + if len(argv) < 2 or argv[1] in ['-h', '--help']: + print 'usage: kallithea/bin/rebranddb.py DBSTRING [NEW] [OLD]' + print ' where DBSTRING is the value of sqlalchemy.db1.url from the .ini,' + print ' NEW defaults to "kallithea", OLD is by default detected from the db"' + raise SystemExit(0) + db = argv[1] + new = 'kallithea' + if len(argv) > 2: + new = argv[2] + old = None + if len(argv) > 3: + old = argv[3] + do_migrate(argv[1], old, new) + +if __name__ == '__main__': + main(sys.argv) diff --git a/rhodecode/bin/template.ini.mako b/kallithea/bin/template.ini.mako rename from rhodecode/bin/template.ini.mako rename to kallithea/bin/template.ini.mako --- a/rhodecode/bin/template.ini.mako +++ b/kallithea/bin/template.ini.mako @@ -1,11 +1,8 @@ ## -*- coding: utf-8 -*- -<%text> -################################################################################ +<%text>################################################################################ ################################################################################ -# RhodeCode - Example config # -# Built-in functions and variables # -# The ${here} variable will be replaced with the parent directory of this file # -# ${uuid()} function will generate a unique hash # +# Kallithea - config file generated with kallithea-config # +################################################################################ ################################################################################ [DEFAULT] @@ -15,14 +12,13 @@ pdebug = false ################################################################################ ## Uncomment and replace with the address which should receive ## ## any error reports after application crash ## -## Additionally those settings will be used by RhodeCode mailing system ## -################################################################################ - +## Additionally those settings will be used by Kallithea mailing system ## +################################################################################ #email_to = admin@localhost #error_email_from = paste_error@localhost -#app_email_from = rhodecode-noreply@localhost +#app_email_from = kallithea-noreply@localhost #error_message = -#email_prefix = [RhodeCode] +#email_prefix = [Kallithea] #smtp_server = mail.server.com #smtp_username = @@ -62,7 +58,7 @@ use = egg:gunicorn#main <%text>## is set to more than one worker workers = 1 <%text>## process name -proc_name = rhodecode +proc_name = kallithea <%text>## type of worker class, one of sync, eventlet, gevent, tornado <%text>## recommended for bigger setup is using of of other than sync one worker_class = sync @@ -77,16 +73,16 @@ timeout = 3600 [uwsgi] socket = /tmp/uwsgi.sock master = true -http = 0.0.0.0:5000 +http = 127.0.0.1:5000 <%text>## set as deamon and redirect all output to file -#daemonize = ./uwsgi_rhodecode.log +#daemonize = ./uwsgi_kallithea.log <%text>## master process PID -pidfile = ./uwsgi_rhodecode.pid +pidfile = ./uwsgi_kallithea.pid <%text>## stats server with workers statistics, use uwsgitop -<%text>## for monitoring +<%text>## for monitoring, `uwsgitop 127.0.0.1:1717` stats = 127.0.0.1:1717 memory-report = true @@ -142,14 +138,14 @@ port = ${port} #prefix = / [app:main] -use = egg:rhodecode +use = egg:kallithea <%text>## enable proxy prefix middleware #filter-with = proxy-prefix full_stack = true static_files = true -<%text>## Optional Languages -<%text>## en, fr, ja, pt_BR, zh_CN, zh_TW, pl, ru +<%text>## Available Languages: +<%text>## de en fr ja pl pt_BR ru zh_CN zh_TW lang = ${lang} cache_dir = ${here}/data index_dir = ${here}/data/index @@ -170,7 +166,7 @@ cut_off_limit = 256000 <%text>## use cache version of scm repo everywhere vcs_full_cache = true -<%text>## force https in RhodeCode, fixes https redirects, assumes it's always https +<%text>## force https in Kallithea, fixes https redirects, assumes it's always https force_https = false <%text>## use Strict-Transport-Security headers @@ -187,7 +183,7 @@ git_path = git <%text>## git rev filter option, --all is the default filter, if you need to <%text>## hide all refs in changelog switch this to --branches --tags -git_rev_filter=--branches --tags +#git_rev_filter = --branches --tags <%text>## RSS feed options rss_cut_off_limit = 256000 @@ -200,8 +196,8 @@ show_revision_number = true <%text>## gist URL alias, used to create nicer urls for gist. This should be an <%text>## url that does rewrites to _admin/gists/. -<%text>## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal -<%text>## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/ +<%text>## example: http://gist.kallithea.server/{gistid}. Empty means use the internal +<%text>## Kallithea url, ie. http[s]://your.kallithea.server/_admin/gists/ gist_alias_url = <%text>## white list of API enabled controllers. This allows to add list of @@ -209,15 +205,20 @@ gist_alias_url = <%text>## api access to raw_files put `FilesController:raw`, to enable access to patches <%text>## add `ChangesetController:changeset_patch`. This list should be "," separated <%text>## Syntax is :. Check debug logs for generated names +<%text>## Recommended settings below are commented out: api_access_controllers_whitelist = +# ChangesetController:changeset_patch, +# ChangesetController:changeset_raw, +# FilesController:raw, +# FilesController:archivefile <%text>## alternative_gravatar_url allows you to use your own avatar server application <%text>## the following parts of the URL will be replaced <%text>## {email} user email <%text>## {md5email} md5 hash of the user email (like at gravatar.com) <%text>## {size} size of the image that is expected from the server application -<%text>## {scheme} http/https from RhodeCode server -<%text>## {netloc} network location from RhodeCode server +<%text>## {scheme} http/https from Kallithea server +<%text>## {netloc} network location from Kallithea server #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size} #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size} @@ -240,8 +241,8 @@ default_encoding = utf8 #clone_uri = {scheme}://{user}{pass}{netloc}{path} -<%text>## issue tracker for RhodeCode (leave blank to disable, absent for default) -#bugtracker = http://bitbucket.org/marcinkuzminski/rhodecode/issues +<%text>## issue tracker for Kallithea (leave blank to disable, absent for default) +#bugtracker = https://bitbucket.org/conservancy/kallithea/issues <%text>## issue tracking mapping for commits messages <%text>## comment out issue_pat, issue_server, issue_prefix to enable @@ -266,7 +267,7 @@ issue_prefix = # <%text>## issue_pat, issue_server_link, issue_prefix can have suffixes to specify <%text>## multiple patterns, to other issues server, wiki or others <%text>## below an example how to create a wiki pattern -<%text>## wiki-some-id -> https://mywiki.com/some-id +# wiki-some-id -> https://mywiki.com/some-id #issue_pat_wiki = (?:wiki-)(.+) #issue_server_link_wiki = https://mywiki.com/{id} @@ -275,8 +276,8 @@ issue_prefix = # <%text>## instance-id prefix <%text>## a prefix key for this instance used for cache invalidation when running -<%text>## multiple instances of rhodecode, make sure it's globally unique for -<%text>## all running rhodecode instances. Leave empty if you don't use it +<%text>## multiple instances of kallithea, make sure it's globally unique for +<%text>## all running kallithea instances. Leave empty if you don't use it instance_id = <%text>## alternative return HTTP header for failed authentication. Default HTTP @@ -306,7 +307,7 @@ broker.port = 5672 broker.user = rabbitmq broker.password = qweqwe -celery.imports = rhodecode.lib.celerylib.tasks +celery.imports = kallithea.lib.celerylib.tasks celery.result.backend = amqp celery.result.dburi = amqp:// @@ -366,7 +367,7 @@ beaker.cache.sql_cache_long.key_length = <%text>## db session ## #beaker.session.type = ext:database -#beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode +#beaker.session.sa.url = postgresql://postgres:qwe@localhost/kallithea #beaker.session.table_name = db_session <%text>## encrypted cookie client side session, good for many instances ## @@ -375,7 +376,7 @@ beaker.cache.sql_cache_long.key_length = <%text>## file based cookies (default) ## #beaker.session.type = file -beaker.session.key = rhodecode +beaker.session.key = kallithea beaker.session.secret = ${uuid()} <%text>## Secure encrypted cookie. Requires AES and AES python libraries @@ -407,7 +408,7 @@ beaker.session.auto = False ### [errormator] ### #################### -## Errormator is tailored to work with RhodeCode, see +## Errormator is tailored to work with Kallithea, see ## http://errormator.com for details how to obtain an account ## you must install python package `errormator_client` to make it work @@ -484,8 +485,7 @@ sentry.exclude_paths = ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ## ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ## ## execute malicious code after an exception is raised. ## -################################################################################ - +################################################################################ set debug = false <%text> ################################## @@ -502,13 +502,13 @@ logview.pylons.util = #eee %if database_engine == 'sqlite': # SQLITE [default] -sqlalchemy.db1.url = sqlite:///${here}/rhodecode.db?timeout=60 +sqlalchemy.db1.url = sqlite:///${here}/kallithea.db?timeout=60 %elif database_engine == 'postgres': # POSTGRESQL -sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode +sqlalchemy.db1.url = postgresql://user:pass@localhost/kallithea %elif database_engine == 'mysql': # MySQL -sqlalchemy.db1.url = mysql://user:pass@localhost/rhodecode +sqlalchemy.db1.url = mysql://user:pass@localhost/kallithea %endif # see sqlalchemy docs for others @@ -521,7 +521,7 @@ sqlalchemy.db1.convert_unicode = true ################################ [loggers] -keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer +keys = root, routes, kallithea, sqlalchemy, beaker, templates, whoosh_indexer [handlers] keys = console, console_sql @@ -556,10 +556,10 @@ handlers = qualname = pylons.templating propagate = 1 -[logger_rhodecode] +[logger_kallithea] level = DEBUG handlers = -qualname = rhodecode +qualname = kallithea propagate = 1 [logger_sqlalchemy] @@ -599,11 +599,11 @@ format = %(asctime)s.%(msecs)03d %(level datefmt = %Y-%m-%d %H:%M:%S [formatter_color_formatter] -class=rhodecode.lib.colored_formatter.ColorFormatter +class=kallithea.lib.colored_formatter.ColorFormatter format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s datefmt = %Y-%m-%d %H:%M:%S [formatter_color_formatter_sql] -class=rhodecode.lib.colored_formatter.ColorFormatterSql +class=kallithea.lib.colored_formatter.ColorFormatterSql format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s datefmt = %Y-%m-%d %H:%M:%S diff --git a/rhodecode/config/__init__.py b/kallithea/config/__init__.py rename from rhodecode/config/__init__.py rename to kallithea/config/__init__.py --- a/rhodecode/config/__init__.py +++ b/kallithea/config/__init__.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . diff --git a/rhodecode/config/conf.py b/kallithea/config/conf.py rename from rhodecode/config/conf.py rename to kallithea/config/conf.py --- a/rhodecode/config/conf.py +++ b/kallithea/config/conf.py @@ -1,18 +1,32 @@ # -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . """ - package.rhodecode.config.conf - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Various config settings for RhodeCode +kallithea.config.conf +~~~~~~~~~~~~~~~~~~~~~ - :created_on: Mar 7, 2012 - :author: marcink - :copyright: (C) 2009-2010 Marcin Kuzminski - :license: , see LICENSE_FILE for more details. +Various config settings for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Mar 7, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. """ -from rhodecode import EXTENSIONS +from kallithea import EXTENSIONS -from rhodecode.lib.utils2 import __get_lem +from kallithea.lib.utils2 import __get_lem # language map is also used by whoosh indexer, which for those specified diff --git a/rhodecode/config/deployment.ini_tmpl b/kallithea/config/deployment.ini_tmpl rename from rhodecode/config/deployment.ini_tmpl rename to kallithea/config/deployment.ini_tmpl --- a/rhodecode/config/deployment.ini_tmpl +++ b/kallithea/config/deployment.ini_tmpl @@ -1,23 +1,25 @@ ################################################################################ ################################################################################ -# RhodeCode - Pylons environment configuration # +# Kallithea - Example config # # # # The %(here)s variable will be replaced with the parent directory of this file# ################################################################################ +################################################################################ [DEFAULT] debug = true pdebug = false + ################################################################################ ## Uncomment and replace with the address which should receive ## ## any error reports after application crash ## -## Additionally those settings will be used by RhodeCode mailing system ## +## Additionally those settings will be used by Kallithea mailing system ## ################################################################################ #email_to = admin@localhost #error_email_from = paste_error@localhost -#app_email_from = rhodecode-noreply@localhost +#app_email_from = kallithea-noreply@localhost #error_message = -#email_prefix = [RhodeCode] +#email_prefix = [Kallithea] #smtp_server = mail.server.com #smtp_username = @@ -54,11 +56,11 @@ max_request_body_size = 107374182400 ## is set to more than one worker #workers = 1 ## process name -#proc_name = rhodecode +#proc_name = kallithea ## type of worker class, one of sync, eventlet, gevent, tornado ## recommended for bigger setup is using of of other than sync one #worker_class = sync -#max_requests = 5 +#max_requests = 1000 ## ammount of time a worker can handle request before it gets killed and ## restarted #timeout = 3600 @@ -71,10 +73,10 @@ max_request_body_size = 107374182400 #http = 127.0.0.1:5000 ## set as deamon and redirect all output to file -#daemonize = ./uwsgi_rhodecode.log +#daemonize = ./uwsgi_kallithea.log ## master process PID -#pidfile = ./uwsgi_rhodecode.pid +#pidfile = ./uwsgi_kallithea.pid ## stats server with workers statistics, use uwsgitop ## for monitoring, `uwsgitop 127.0.0.1:1717` @@ -133,24 +135,24 @@ port = 5000 #prefix = / [app:main] -use = egg:rhodecode +use = egg:kallithea ## enable proxy prefix middleware #filter-with = proxy-prefix full_stack = true static_files = true -## Optional Languages -## en, fr, ja, pt_BR, zh_CN, zh_TW, pl +## Available Languages: +## de en fr ja pl pt_BR ru zh_CN zh_TW lang = en cache_dir = %(here)s/data index_dir = %(here)s/data/index ## perform a full repository scan on each server start, this should be ## set to false after first startup, to allow faster server restarts. -initial_repo_scan = true +initial_repo_scan = false ## uncomment and set this path to use archive download cache -#archive_cache_dir = /tmp/tarballcache +archive_cache_dir = %(here)s/tarballcache ## change this to unique ID for security app_instance_uuid = ${app_instance_uuid} @@ -161,7 +163,7 @@ cut_off_limit = 256000 ## use cache version of scm repo everywhere vcs_full_cache = true -## force https in RhodeCode, fixes https redirects, assumes it's always https +## force https in Kallithea, fixes https redirects, assumes it's always https force_https = false ## use Strict-Transport-Security headers @@ -178,7 +180,7 @@ git_path = git ## git rev filter option, --all is the default filter, if you need to ## hide all refs in changelog switch this to --branches --tags -git_rev_filter=--all +#git_rev_filter = --branches --tags ## RSS feed options rss_cut_off_limit = 256000 @@ -191,8 +193,8 @@ show_revision_number = true ## gist URL alias, used to create nicer urls for gist. This should be an ## url that does rewrites to _admin/gists/. -## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal -## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/ +## example: http://gist.kallithea.server/{gistid}. Empty means use the internal +## Kallithea url, ie. http[s]://your.kallithea.server/_admin/gists/ gist_alias_url = ## white list of API enabled controllers. This allows to add list of @@ -200,7 +202,7 @@ gist_alias_url = ## api access to raw_files put `FilesController:raw`, to enable access to patches ## add `ChangesetController:changeset_patch`. This list should be "," separated ## Syntax is :. Check debug logs for generated names -## Recommended settings bellow are commented out: +## Recommended settings below are commented out: api_access_controllers_whitelist = # ChangesetController:changeset_patch, # ChangesetController:changeset_raw, @@ -212,8 +214,8 @@ api_access_controllers_whitelist = ## {email} user email ## {md5email} md5 hash of the user email (like at gravatar.com) ## {size} size of the image that is expected from the server application -## {scheme} http/https from RhodeCode server -## {netloc} network location from RhodeCode server +## {scheme} http/https from Kallithea server +## {netloc} network location from Kallithea server #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size} #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size} @@ -236,8 +238,8 @@ default_encoding = utf8 #clone_uri = {scheme}://{user}{pass}{netloc}{path} -## issue tracker for RhodeCode (leave blank to disable, absent for default) -#bugtracker = http://bitbucket.org/marcinkuzminski/rhodecode/issues +## issue tracker for Kallithea (leave blank to disable, absent for default) +#bugtracker = https://bitbucket.org/conservancy/kallithea/issues ## issue tracking mapping for commits messages ## comment out issue_pat, issue_server, issue_prefix to enable @@ -262,7 +264,7 @@ issue_prefix = # ## issue_pat, issue_server_link, issue_prefix can have suffixes to specify ## multiple patterns, to other issues server, wiki or others ## below an example how to create a wiki pattern -# #wiki-some-id -> https://mywiki.com/some-id +# wiki-some-id -> https://mywiki.com/some-id #issue_pat_wiki = (?:wiki-)(.+) #issue_server_link_wiki = https://mywiki.com/{id} @@ -271,8 +273,8 @@ issue_prefix = # ## instance-id prefix ## a prefix key for this instance used for cache invalidation when running -## multiple instances of rhodecode, make sure it's globally unique for -## all running rhodecode instances. Leave empty if you don't use it +## multiple instances of kallithea, make sure it's globally unique for +## all running kallithea instances. Leave empty if you don't use it instance_id = ## alternative return HTTP header for failed authentication. Default HTTP @@ -294,6 +296,7 @@ allow_custom_hooks_settings = True #################################### ### CELERY CONFIG #### #################################### + use_celery = false broker.host = localhost broker.vhost = rabbitmqhost @@ -301,7 +304,7 @@ broker.port = 5672 broker.user = rabbitmq broker.password = qweqwe -celery.imports = rhodecode.lib.celerylib.tasks +celery.imports = kallithea.lib.celerylib.tasks celery.result.backend = amqp celery.result.dburi = amqp:// @@ -321,6 +324,7 @@ celery.always.eager = false #################################### ### BEAKER CACHE #### #################################### + beaker.cache.data_dir=%(here)s/data/cache/data beaker.cache.lock_dir=%(here)s/data/cache/lock @@ -360,7 +364,7 @@ beaker.cache.sql_cache_long.key_length = ## db session ## #beaker.session.type = ext:database -#beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode +#beaker.session.sa.url = postgresql://postgres:qwe@localhost/kallithea #beaker.session.table_name = db_session ## encrypted cookie client side session, good for many instances ## @@ -369,7 +373,7 @@ beaker.cache.sql_cache_long.key_length = ## file based cookies (default) ## #beaker.session.type = file -beaker.session.key = rhodecode +beaker.session.key = kallithea beaker.session.secret = ${app_instance_uuid} ## Secure encrypted cookie. Requires AES and AES python libraries @@ -400,7 +404,7 @@ beaker.session.auto = False ### [errormator] ### #################### -## Errormator is tailored to work with RhodeCode, see +## Errormator is tailored to work with Kallithea, see ## http://errormator.com for details how to obtain an account ## you must install python package `errormator_client` to make it work @@ -483,6 +487,7 @@ set debug = false ################################## ### LOGVIEW CONFIG ### ################################## + logview.sqlalchemy = #faa logview.pylons.templating = #bfb logview.pylons.util = #eee @@ -492,13 +497,13 @@ logview.pylons.util = #eee ######################################################### # SQLITE [default] -sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30 +sqlalchemy.db1.url = sqlite:///%(here)s/kallithea.db?timeout=60 # POSTGRESQL -# sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode +# sqlalchemy.db1.url = postgresql://user:pass@localhost/kallithea # MySQL -# sqlalchemy.db1.url = mysql://user:pass@localhost/rhodecode +# sqlalchemy.db1.url = mysql://user:pass@localhost/kallithea # see sqlalchemy docs for others @@ -509,8 +514,9 @@ sqlalchemy.db1.convert_unicode = true ################################ ### LOGGING CONFIGURATION #### ################################ + [loggers] -keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer +keys = root, routes, kallithea, sqlalchemy, beaker, templates, whoosh_indexer [handlers] keys = console, console_sql @@ -521,6 +527,7 @@ keys = generic, color_formatter, color_f ############# ## LOGGERS ## ############# + [logger_root] level = NOTSET handlers = console @@ -544,10 +551,10 @@ handlers = qualname = pylons.templating propagate = 1 -[logger_rhodecode] +[logger_kallithea] level = DEBUG handlers = -qualname = rhodecode +qualname = kallithea propagate = 1 [logger_sqlalchemy] @@ -587,11 +594,11 @@ format = %(asctime)s.%(msecs)03d %(level datefmt = %Y-%m-%d %H:%M:%S [formatter_color_formatter] -class=rhodecode.lib.colored_formatter.ColorFormatter +class=kallithea.lib.colored_formatter.ColorFormatter format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s datefmt = %Y-%m-%d %H:%M:%S [formatter_color_formatter_sql] -class=rhodecode.lib.colored_formatter.ColorFormatterSql +class=kallithea.lib.colored_formatter.ColorFormatterSql format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s datefmt = %Y-%m-%d %H:%M:%S diff --git a/rhodecode/config/environment.py b/kallithea/config/environment.py rename from rhodecode/config/environment.py rename to kallithea/config/environment.py --- a/rhodecode/config/environment.py +++ b/kallithea/config/environment.py @@ -1,33 +1,50 @@ -"""Pylons environment configuration""" +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" + Pylons environment configuration +""" import os import logging -import rhodecode +import kallithea +import platform from mako.lookup import TemplateLookup from pylons.configuration import PylonsConfig from pylons.error import handle_mako_error # don't remove this import it does magic for celery -from rhodecode.lib import celerypylons +from kallithea.lib import celerypylons -import rhodecode.lib.app_globals as app_globals +import kallithea.lib.app_globals as app_globals -from rhodecode.config.routing import make_map +from kallithea.config.routing import make_map -from rhodecode.lib import helpers -from rhodecode.lib.auth import set_available_permissions -from rhodecode.lib.utils import repo2db_mapper, make_ui, set_rhodecode_config,\ +from kallithea.lib import helpers +from kallithea.lib.auth import set_available_permissions +from kallithea.lib.utils import repo2db_mapper, make_ui, set_app_settings,\ load_rcextensions, check_git_version, set_vcs_config -from rhodecode.lib.utils2 import engine_from_config, str2bool -from rhodecode.lib.db_manage import DbManage -from rhodecode.model import init_model -from rhodecode.model.scm import ScmModel +from kallithea.lib.utils2 import engine_from_config, str2bool +from kallithea.lib.db_manage import DbManage +from kallithea.model import init_model +from kallithea.model.scm import ScmModel log = logging.getLogger(__name__) -def load_environment(global_conf, app_conf, initial=False): +def load_environment(global_conf, app_conf, initial=False, + test_env=None, test_index=None): """ Configure the Pylons environment via the ``pylons.config`` object @@ -44,16 +61,16 @@ def load_environment(global_conf, app_co ) # Initialize config with the basic options - config.init_app(global_conf, app_conf, package='rhodecode', paths=paths) + config.init_app(global_conf, app_conf, package='kallithea', paths=paths) - # store some globals into rhodecode - rhodecode.CELERY_ON = str2bool(config['app_conf'].get('use_celery')) - rhodecode.CELERY_EAGER = str2bool(config['app_conf'].get('celery.always.eager')) + # store some globals into kallithea + kallithea.CELERY_ON = str2bool(config['app_conf'].get('use_celery')) + kallithea.CELERY_EAGER = str2bool(config['app_conf'].get('celery.always.eager')) config['routes.map'] = make_map(config) config['pylons.app_globals'] = app_globals.Globals(config) config['pylons.h'] = helpers - rhodecode.CONFIG = config + kallithea.CONFIG = config load_rcextensions(root_path=config['here']) @@ -73,18 +90,22 @@ def load_environment(global_conf, app_co config['pylons.strict_tmpl_context'] = True test = os.path.split(config['__file__'])[-1] == 'test.ini' if test: + if test_env is None: + test_env = not int(os.environ.get('KALLITHEA_NO_TMP_PATH', 0)) + if test_index is None: + test_index = not int(os.environ.get('KALLITHEA_WHOOSH_TEST_DISABLE', 0)) if os.environ.get('TEST_DB'): # swap config if we pass enviroment variable config['sqlalchemy.db1.url'] = os.environ.get('TEST_DB') - from rhodecode.lib.utils import create_test_env, create_test_index - from rhodecode.tests import TESTS_TMP_PATH - # set RC_NO_TMP_PATH=1 to disable re-creating the database and - # test repos - if not int(os.environ.get('RC_NO_TMP_PATH', 0)): + from kallithea.lib.utils import create_test_env, create_test_index + from kallithea.tests import TESTS_TMP_PATH + #set KALLITHEA_NO_TMP_PATH=1 to disable re-creating the database and + #test repos + if test_env: create_test_env(TESTS_TMP_PATH, config) - # set RC_WHOOSH_TEST_DISABLE=1 to disable whoosh index during tests - if not int(os.environ.get('RC_WHOOSH_TEST_DISABLE', 0)): + #set KALLITHEA_WHOOSH_TEST_DISABLE=1 to disable whoosh index during tests + if test_index: create_test_index(TESTS_TMP_PATH, config, True) DbManage.check_waitress() @@ -96,20 +117,20 @@ def load_environment(global_conf, app_co set_available_permissions(config) repos_path = make_ui('db').configitems('paths')[0][1] config['base_path'] = repos_path - set_rhodecode_config(config) + set_app_settings(config) - instance_id = rhodecode.CONFIG.get('instance_id') + instance_id = kallithea.CONFIG.get('instance_id') if instance_id == '*': - instance_id = '%s-%s' % (os.uname()[1], os.getpid()) - rhodecode.CONFIG['instance_id'] = instance_id + instance_id = '%s-%s' % (platform.uname()[1], os.getpid()) + kallithea.CONFIG['instance_id'] = instance_id # CONFIGURATION OPTIONS HERE (note: all config options will override # any Pylons config options) # store config reference into our module to skip import magic of # pylons - rhodecode.CONFIG.update(config) - set_vcs_config(rhodecode.CONFIG) + kallithea.CONFIG.update(config) + set_vcs_config(kallithea.CONFIG) #check git version check_git_version() diff --git a/rhodecode/config/middleware.py b/kallithea/config/middleware.py rename from rhodecode/config/middleware.py rename to kallithea/config/middleware.py --- a/rhodecode/config/middleware.py +++ b/kallithea/config/middleware.py @@ -1,4 +1,19 @@ -"""Pylons middleware initialization""" +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" + Pylons middleware initialization +""" from beaker.middleware import SessionMiddleware from routes.middleware import RoutesMiddleware @@ -11,11 +26,11 @@ from paste.gzipper import make_gzip_midd from pylons.middleware import ErrorHandler, StatusCodeRedirect from pylons.wsgiapp import PylonsApp -from rhodecode.lib.middleware.simplehg import SimpleHg -from rhodecode.lib.middleware.simplegit import SimpleGit -from rhodecode.lib.middleware.https_fixup import HttpsFixup -from rhodecode.config.environment import load_environment -from rhodecode.lib.middleware.wrapper import RequestWrapper +from kallithea.lib.middleware.simplehg import SimpleHg +from kallithea.lib.middleware.simplegit import SimpleGit +from kallithea.lib.middleware.https_fixup import HttpsFixup +from kallithea.config.environment import load_environment +from kallithea.lib.middleware.wrapper import RequestWrapper def make_app(global_conf, full_stack=True, static_files=True, **app_conf): @@ -49,13 +64,13 @@ def make_app(global_conf, full_stack=Tru # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(config['pdebug']): - from rhodecode.lib.profiler import ProfilingMiddleware + from kallithea.lib.profiler import ProfilingMiddleware app = ProfilingMiddleware(app) if asbool(full_stack): - from rhodecode.lib.middleware.sentry import Sentry - from rhodecode.lib.middleware.errormator import Errormator + from kallithea.lib.middleware.sentry import Sentry + from kallithea.lib.middleware.errormator import Errormator if Errormator and asbool(config['app_conf'].get('errormator')): app = Errormator(app, config) elif Sentry: diff --git a/rhodecode/config/post_receive_tmpl.py b/kallithea/config/post_receive_tmpl.py rename from rhodecode/config/post_receive_tmpl.py rename to kallithea/config/post_receive_tmpl.py --- a/rhodecode/config/post_receive_tmpl.py +++ b/kallithea/config/post_receive_tmpl.py @@ -3,28 +3,31 @@ import os import sys try: - import rhodecode - RC_HOOK_VER = '_TMPL_' - os.environ['RC_HOOK_VER'] = RC_HOOK_VER - from rhodecode.lib.hooks import handle_git_post_receive + import kallithea + KALLITHEA_HOOK_VER = '_TMPL_' + os.environ['KALLITHEA_HOOK_VER'] = KALLITHEA_HOOK_VER + from kallithea.lib.hooks import handle_git_post_receive as _handler except ImportError: - rhodecode = None + if os.environ.get('RC_DEBUG_GIT_HOOK'): + import traceback + print traceback.format_exc() + kallithea = None def main(): - if rhodecode is None: - # exit with success if we cannot import rhodecode !! + if kallithea is None: + # exit with success if we cannot import kallithea !! # this allows simply push to this repo even without - # rhodecode + # kallithea sys.exit(0) repo_path = os.path.abspath('.') push_data = sys.stdin.readlines() # os.environ is modified here by a subprocess call that # runs git and later git executes this hook. - # Environ gets some additional info from rhodecode system + # Environ gets some additional info from kallithea system # like IP or username from basic-auth - handle_git_post_receive(repo_path, push_data, os.environ) + _handler(repo_path, push_data, os.environ) sys.exit(0) if __name__ == '__main__': diff --git a/rhodecode/config/pre_receive_tmpl.py b/kallithea/config/pre_receive_tmpl.py rename from rhodecode/config/pre_receive_tmpl.py rename to kallithea/config/pre_receive_tmpl.py --- a/rhodecode/config/pre_receive_tmpl.py +++ b/kallithea/config/pre_receive_tmpl.py @@ -3,28 +3,31 @@ import os import sys try: - import rhodecode - RC_HOOK_VER = '_TMPL_' - os.environ['RC_HOOK_VER'] = RC_HOOK_VER - from rhodecode.lib.hooks import handle_git_pre_receive + import kallithea + KALLITHEA_HOOK_VER = '_TMPL_' + os.environ['KALLITHEA_HOOK_VER'] = KALLITHEA_HOOK_VER + from kallithea.lib.hooks import handle_git_pre_receive as _handler except ImportError: - rhodecode = None + if os.environ.get('RC_DEBUG_GIT_HOOK'): + import traceback + print traceback.format_exc() + kallithea = None def main(): - if rhodecode is None: - # exit with success if we cannot import rhodecode !! + if kallithea is None: + # exit with success if we cannot import kallithea !! # this allows simply push to this repo even without - # rhodecode + # kallithea sys.exit(0) repo_path = os.path.abspath('.') push_data = sys.stdin.readlines() # os.environ is modified here by a subprocess call that # runs git and later git executes this hook. - # Environ gets some additional info from rhodecode system + # Environ gets some additional info from kallithea system # like IP or username from basic-auth - handle_git_pre_receive(repo_path, push_data, os.environ) + _handler(repo_path, push_data, os.environ) sys.exit(0) if __name__ == '__main__': diff --git a/rhodecode/config/rcextensions/__init__.py b/kallithea/config/rcextensions/__init__.py rename from rhodecode/config/rcextensions/__init__.py rename to kallithea/config/rcextensions/__init__.py --- a/rhodecode/config/rcextensions/__init__.py +++ b/kallithea/config/rcextensions/__init__.py @@ -173,7 +173,7 @@ DELETE_USER_HOOK = _dluserhook #============================================================================== # this function will be executed after each push it's executed after the -# build-in hook that RhodeCode uses for logging pushes +# build-in hook that Kallithea uses for logging pushes def _pushhook(*args, **kwargs): """ Post push hook @@ -197,7 +197,7 @@ PUSH_HOOK = _pushhook #============================================================================== # this function will be executed after each push it's executed after the -# build-in hook that RhodeCode uses for logging pulls +# build-in hook that Kallithea uses for logging pulls def _pullhook(*args, **kwargs): """ Post pull hook diff --git a/rhodecode/config/routing.py b/kallithea/config/routing.py rename from rhodecode/config/routing.py rename to kallithea/config/routing.py --- a/rhodecode/config/routing.py +++ b/kallithea/config/routing.py @@ -1,3 +1,16 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . """ Routes configuration @@ -5,6 +18,7 @@ The more specific and detailed routes sh may take precedent over the more generic routes. For more information refer to the routes manual at http://routes.groovie.org/docs/ """ + from __future__ import with_statement from routes import Mapper @@ -15,12 +29,12 @@ ADMIN_PREFIX = '/_admin' def make_map(config): """Create, configure and return the routes Mapper""" rmap = Mapper(directory=config['pylons.paths']['controllers'], - always_scan=config['debug']) + always_scan=config['debug']) rmap.minimization = False rmap.explicit = False - from rhodecode.lib.utils import is_valid_repo - from rhodecode.lib.utils import is_valid_repos_group + from kallithea.lib.utils import (is_valid_repo, is_valid_repo_group, + get_repo_by_id) def check_repo(environ, match_dict): """ @@ -29,20 +43,16 @@ def make_map(config): :param environ: :param match_dict: """ - from rhodecode.model.db import Repository repo_name = match_dict.get('repo_name') if match_dict.get('f_path'): #fix for multiple initial slashes that causes errors match_dict['f_path'] = match_dict['f_path'].lstrip('/') - try: - by_id = repo_name.split('_') - if len(by_id) == 2 and by_id[1].isdigit() and by_id[0] == '': - repo_name = Repository.get(by_id[1]).repo_name - match_dict['repo_name'] = repo_name - except Exception: - pass + by_id_match = get_repo_by_id(repo_name) + if by_id_match: + repo_name = by_id_match + match_dict['repo_name'] = repo_name return is_valid_repo(repo_name, config['base_path']) @@ -53,8 +63,8 @@ def make_map(config): :param environ: :param match_dict: """ - repos_group_name = match_dict.get('group_name') - return is_valid_repos_group(repos_group_name, config['base_path']) + repo_group_name = match_dict.get('group_name') + return is_valid_repo_group(repo_group_name, config['base_path']) def check_group_skip_path(environ, match_dict): """ @@ -64,9 +74,9 @@ def make_map(config): :param environ: :param match_dict: """ - repos_group_name = match_dict.get('group_name') - return is_valid_repos_group(repos_group_name, config['base_path'], - skip_path_check=True) + repo_group_name = match_dict.get('group_name') + return is_valid_repo_group(repo_group_name, config['base_path'], + skip_path_check=True) def check_user_group(environ, match_dict): """ @@ -91,131 +101,83 @@ def make_map(config): #MAIN PAGE rmap.connect('home', '/', controller='home', action='index') - rmap.connect('repo_switcher', '/repos', controller='home', - action='repo_switcher') - rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*?}', - controller='home', action='branch_tag_switcher') + rmap.connect('about', '/about', controller='home', action='about') + rmap.connect('repo_switcher_data', '/_repos', controller='home', + action='repo_switcher_data') + rmap.connect('rst_help', "http://docutils.sourceforge.net/docs/user/rst/quickref.html", _static=True) - rmap.connect('rhodecode_official', "http://rhodecode.org", _static=True) + rmap.connect('kallithea_project_url', "https://kallithea-scm.org/", _static=True) + rmap.connect('issues_url', 'https://bitbucket.org/conservancy/kallithea/issues', _static=True) - #ADMIN REPOSITORY REST ROUTES + #ADMIN REPOSITORY ROUTES with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='admin/repos') as m: m.connect("repos", "/repos", - action="create", conditions=dict(method=["POST"])) + action="create", conditions=dict(method=["POST"])) m.connect("repos", "/repos", - action="index", conditions=dict(method=["GET"])) - m.connect("formatted_repos", "/repos.{format}", - action="index", - conditions=dict(method=["GET"])) + action="index", conditions=dict(method=["GET"])) m.connect("new_repo", "/create_repository", action="create_repository", conditions=dict(method=["GET"])) m.connect("/repos/{repo_name:.*?}", - action="update", conditions=dict(method=["PUT"], - function=check_repo)) - m.connect("/repos/{repo_name:.*?}", - action="delete", conditions=dict(method=["DELETE"], - function=check_repo)) - m.connect("formatted_edit_repo", "/repos/{repo_name:.*?}.{format}/edit", - action="edit", conditions=dict(method=["GET"], - function=check_repo)) + action="update", conditions=dict(method=["PUT"], + function=check_repo)) + m.connect("delete_repo", "/repos/{repo_name:.*?}", + action="delete", conditions=dict(method=["DELETE"], + )) m.connect("repo", "/repos/{repo_name:.*?}", - action="show", conditions=dict(method=["GET"], - function=check_repo)) - m.connect("formatted_repo", "/repos/{repo_name:.*?}.{format}", - action="show", conditions=dict(method=["GET"], - function=check_repo)) - #add repo perm member - m.connect('set_repo_perm_member', - "/repos/{repo_name:.*?}/grant_perm", - action="set_repo_perm_member", - conditions=dict(method=["POST"], function=check_repo)) - - #ajax delete repo perm user - m.connect('delete_repo_perm_member', - "/repos/{repo_name:.*?}/revoke_perm", - action="delete_repo_perm_member", - conditions=dict(method=["DELETE"], function=check_repo)) + action="show", conditions=dict(method=["GET"], + function=check_repo)) - #settings actions - m.connect('repo_stats', "/repos_stats/{repo_name:.*?}", - action="repo_stats", conditions=dict(method=["DELETE"], - function=check_repo)) - m.connect('repo_cache', "/repos_cache/{repo_name:.*?}", - action="repo_cache", conditions=dict(method=["DELETE"], - function=check_repo)) - m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*?}", - action="repo_public_journal", conditions=dict(method=["PUT"], - function=check_repo)) - m.connect('repo_pull', "/repo_pull/{repo_name:.*?}", - action="repo_pull", conditions=dict(method=["PUT"], - function=check_repo)) - m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*?}", - action="repo_as_fork", conditions=dict(method=["PUT"], - function=check_repo)) - m.connect('repo_locking', "/repo_locking/{repo_name:.*?}", - action="repo_locking", conditions=dict(method=["PUT"], - function=check_repo)) - m.connect('toggle_locking', "/locking_toggle/{repo_name:.*?}", - action="toggle_locking", conditions=dict(method=["GET"], - function=check_repo)) - - #repo fields - m.connect('create_repo_fields', "/repo_fields/{repo_name:.*?}/new", - action="create_repo_field", conditions=dict(method=["PUT"], - function=check_repo)) - - m.connect('delete_repo_fields', "/repo_fields/{repo_name:.*?}/{field_id}", - action="delete_repo_field", conditions=dict(method=["DELETE"], - function=check_repo)) - + #ADMIN REPOSITORY GROUPS ROUTES with rmap.submapper(path_prefix=ADMIN_PREFIX, - controller='admin/repos_groups') as m: - m.connect("repos_groups", "/repos_groups", + controller='admin/repo_groups') as m: + m.connect("repos_groups", "/repo_groups", action="create", conditions=dict(method=["POST"])) - m.connect("repos_groups", "/repos_groups", + m.connect("repos_groups", "/repo_groups", action="index", conditions=dict(method=["GET"])) - m.connect("formatted_repos_groups", "/repos_groups.{format}", - action="index", conditions=dict(method=["GET"])) - m.connect("new_repos_group", "/repos_groups/new", + m.connect("new_repos_group", "/repo_groups/new", action="new", conditions=dict(method=["GET"])) - m.connect("formatted_new_repos_group", "/repos_groups/new.{format}", - action="new", conditions=dict(method=["GET"])) - m.connect("update_repos_group", "/repos_groups/{group_name:.*?}", + m.connect("update_repos_group", "/repo_groups/{group_name:.*?}", action="update", conditions=dict(method=["PUT"], function=check_group)) - #add repo group perm member - m.connect('set_repo_group_perm_member', - "/repos_groups/{group_name:.*?}/grant_perm", - action="set_repo_group_perm_member", - conditions=dict(method=["POST"], function=check_group)) - #ajax delete repo group perm - m.connect('delete_repo_group_perm_member', - "/repos_groups/{group_name:.*?}/revoke_perm", - action="delete_repo_group_perm_member", - conditions=dict(method=["DELETE"], function=check_group)) - - m.connect("delete_repos_group", "/repos_groups/{group_name:.*?}", - action="delete", conditions=dict(method=["DELETE"], - function=check_group_skip_path)) - m.connect("edit_repos_group", "/repos_groups/{group_name:.*?}/edit", - action="edit", conditions=dict(method=["GET"], - function=check_group)) - m.connect("formatted_edit_repos_group", - "/repos_groups/{group_name:.*?}.{format}/edit", - action="edit", conditions=dict(method=["GET"], - function=check_group)) - m.connect("repos_group", "/repos_groups/{group_name:.*?}", - action="show", conditions=dict(method=["GET"], - function=check_group)) - m.connect("formatted_repos_group", "/repos_groups/{group_name:.*?}.{format}", + m.connect("repos_group", "/repo_groups/{group_name:.*?}", action="show", conditions=dict(method=["GET"], function=check_group)) - #ADMIN USER REST ROUTES + #EXTRAS REPO GROUP ROUTES + m.connect("edit_repo_group", "/repo_groups/{group_name:.*?}/edit", + action="edit", + conditions=dict(method=["GET"], function=check_group)) + m.connect("edit_repo_group", "/repo_groups/{group_name:.*?}/edit", + action="edit", + conditions=dict(method=["PUT"], function=check_group)) + + m.connect("edit_repo_group_advanced", "/repo_groups/{group_name:.*?}/edit/advanced", + action="edit_repo_group_advanced", + conditions=dict(method=["GET"], function=check_group)) + m.connect("edit_repo_group_advanced", "/repo_groups/{group_name:.*?}/edit/advanced", + action="edit_repo_group_advanced", + conditions=dict(method=["PUT"], function=check_group)) + + m.connect("edit_repo_group_perms", "/repo_groups/{group_name:.*?}/edit/permissions", + action="edit_repo_group_perms", + conditions=dict(method=["GET"], function=check_group)) + m.connect("edit_repo_group_perms", "/repo_groups/{group_name:.*?}/edit/permissions", + action="update_perms", + conditions=dict(method=["PUT"], function=check_group)) + m.connect("edit_repo_group_perms", "/repo_groups/{group_name:.*?}/edit/permissions", + action="delete_perms", + conditions=dict(method=["DELETE"], function=check_group)) + + m.connect("delete_repos_group", "/repo_groups/{group_name:.*?}", + action="delete", conditions=dict(method=["DELETE"], + function=check_group_skip_path)) + + + #ADMIN USER ROUTES with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='admin/users') as m: m.connect("users", "/users", @@ -226,131 +188,204 @@ def make_map(config): action="index", conditions=dict(method=["GET"])) m.connect("new_user", "/users/new", action="new", conditions=dict(method=["GET"])) - m.connect("formatted_new_user", "/users/new.{format}", - action="new", conditions=dict(method=["GET"])) m.connect("update_user", "/users/{id}", action="update", conditions=dict(method=["PUT"])) m.connect("delete_user", "/users/{id}", action="delete", conditions=dict(method=["DELETE"])) m.connect("edit_user", "/users/{id}/edit", action="edit", conditions=dict(method=["GET"])) - m.connect("formatted_edit_user", - "/users/{id}.{format}/edit", - action="edit", conditions=dict(method=["GET"])) m.connect("user", "/users/{id}", action="show", conditions=dict(method=["GET"])) - m.connect("formatted_user", "/users/{id}.{format}", - action="show", conditions=dict(method=["GET"])) #EXTRAS USER ROUTES - m.connect("user_perm", "/users_perm/{id}", - action="update_perm", conditions=dict(method=["PUT"])) - m.connect("user_emails", "/users_emails/{id}", + m.connect("edit_user_advanced", "/users/{id}/edit/advanced", + action="edit_advanced", conditions=dict(method=["GET"])) + m.connect("edit_user_advanced", "/users/{id}/edit/advanced", + action="update_advanced", conditions=dict(method=["PUT"])) + + m.connect("edit_user_api_keys", "/users/{id}/edit/api_keys", + action="edit_api_keys", conditions=dict(method=["GET"])) + m.connect("edit_user_api_keys", "/users/{id}/edit/api_keys", + action="add_api_key", conditions=dict(method=["PUT"])) + m.connect("edit_user_api_keys", "/users/{id}/edit/api_keys", + action="delete_api_key", conditions=dict(method=["DELETE"])) + + m.connect("edit_user_perms", "/users/{id}/edit/permissions", + action="edit_perms", conditions=dict(method=["GET"])) + m.connect("edit_user_perms", "/users/{id}/edit/permissions", + action="update_perms", conditions=dict(method=["PUT"])) + + m.connect("edit_user_emails", "/users/{id}/edit/emails", + action="edit_emails", conditions=dict(method=["GET"])) + m.connect("edit_user_emails", "/users/{id}/edit/emails", action="add_email", conditions=dict(method=["PUT"])) - m.connect("user_emails_delete", "/users_emails/{id}", + m.connect("edit_user_emails", "/users/{id}/edit/emails", action="delete_email", conditions=dict(method=["DELETE"])) - m.connect("user_ips", "/users_ips/{id}", + + m.connect("edit_user_ips", "/users/{id}/edit/ips", + action="edit_ips", conditions=dict(method=["GET"])) + m.connect("edit_user_ips", "/users/{id}/edit/ips", action="add_ip", conditions=dict(method=["PUT"])) - m.connect("user_ips_delete", "/users_ips/{id}", + m.connect("edit_user_ips", "/users/{id}/edit/ips", action="delete_ip", conditions=dict(method=["DELETE"])) #ADMIN USER GROUPS REST ROUTES with rmap.submapper(path_prefix=ADMIN_PREFIX, - controller='admin/users_groups') as m: - m.connect("users_groups", "/users_groups", + controller='admin/user_groups') as m: + m.connect("users_groups", "/user_groups", action="create", conditions=dict(method=["POST"])) - m.connect("users_groups", "/users_groups", - action="index", conditions=dict(method=["GET"])) - m.connect("formatted_users_groups", "/users_groups.{format}", + m.connect("users_groups", "/user_groups", action="index", conditions=dict(method=["GET"])) - m.connect("new_users_group", "/users_groups/new", - action="new", conditions=dict(method=["GET"])) - m.connect("formatted_new_users_group", "/users_groups/new.{format}", + m.connect("new_users_group", "/user_groups/new", action="new", conditions=dict(method=["GET"])) - m.connect("update_users_group", "/users_groups/{id}", + m.connect("update_users_group", "/user_groups/{id}", action="update", conditions=dict(method=["PUT"])) - m.connect("delete_users_group", "/users_groups/{id}", + m.connect("delete_users_group", "/user_groups/{id}", action="delete", conditions=dict(method=["DELETE"])) - m.connect("edit_users_group", "/users_groups/{id}/edit", + m.connect("edit_users_group", "/user_groups/{id}/edit", action="edit", conditions=dict(method=["GET"]), function=check_user_group) - m.connect("formatted_edit_users_group", - "/users_groups/{id}.{format}/edit", - action="edit", conditions=dict(method=["GET"])) - m.connect("users_group", "/users_groups/{id}", - action="show", conditions=dict(method=["GET"])) - m.connect("formatted_users_group", "/users_groups/{id}.{format}", + m.connect("users_group", "/user_groups/{id}", action="show", conditions=dict(method=["GET"])) - #EXTRAS USER ROUTES - # update - m.connect("users_group_perm", "/users_groups/{id}/update_global_perm", - action="update_perm", conditions=dict(method=["PUT"])) + #EXTRAS USER GROUP ROUTES + m.connect("edit_user_group_default_perms", "/user_groups/{id}/edit/default_perms", + action="edit_default_perms", conditions=dict(method=["GET"])) + m.connect("edit_user_group_default_perms", "/user_groups/{id}/edit/default_perms", + action="update_default_perms", conditions=dict(method=["PUT"])) + - #add user group perm member - m.connect('set_user_group_perm_member', "/users_groups/{id}/grant_perm", - action="set_user_group_perm_member", - conditions=dict(method=["POST"])) + m.connect("edit_user_group_perms", "/user_groups/{id}/edit/perms", + action="edit_perms", conditions=dict(method=["GET"])) + m.connect("edit_user_group_perms", "/user_groups/{id}/edit/perms", + action="update_perms", conditions=dict(method=["PUT"])) + m.connect("edit_user_group_perms", "/user_groups/{id}/edit/perms", + action="delete_perms", conditions=dict(method=["DELETE"])) + + m.connect("edit_user_group_advanced", "/user_groups/{id}/edit/advanced", + action="edit_advanced", conditions=dict(method=["GET"])) + + m.connect("edit_user_group_members", "/user_groups/{id}/edit/members", + action="edit_members", conditions=dict(method=["GET"])) - #ajax delete user group perm - m.connect('delete_user_group_perm_member', "/users_groups/{id}/revoke_perm", - action="delete_user_group_perm_member", - conditions=dict(method=["DELETE"])) + + + #ADMIN PERMISSIONS ROUTES + with rmap.submapper(path_prefix=ADMIN_PREFIX, + controller='admin/permissions') as m: + m.connect("admin_permissions", "/permissions", + action="permission_globals", conditions=dict(method=["POST"])) + m.connect("admin_permissions", "/permissions", + action="permission_globals", conditions=dict(method=["GET"])) - #ADMIN GROUP REST ROUTES - rmap.resource('group', 'groups', - controller='admin/groups', path_prefix=ADMIN_PREFIX) + m.connect("admin_permissions_ips", "/permissions/ips", + action="permission_ips", conditions=dict(method=["POST"])) + m.connect("admin_permissions_ips", "/permissions/ips", + action="permission_ips", conditions=dict(method=["GET"])) - #ADMIN PERMISSIONS REST ROUTES - rmap.resource('permission', 'permissions', - controller='admin/permissions', path_prefix=ADMIN_PREFIX) + m.connect("admin_permissions_perms", "/permissions/perms", + action="permission_perms", conditions=dict(method=["POST"])) + m.connect("admin_permissions_perms", "/permissions/perms", + action="permission_perms", conditions=dict(method=["GET"])) + #ADMIN DEFAULTS REST ROUTES rmap.resource('default', 'defaults', controller='admin/defaults', path_prefix=ADMIN_PREFIX) - ##ADMIN LDAP SETTINGS - rmap.connect('ldap_settings', '%s/ldap' % ADMIN_PREFIX, - controller='admin/ldap_settings', action='ldap_settings', + #ADMIN AUTH SETTINGS + rmap.connect('auth_settings', '%s/auth' % ADMIN_PREFIX, + controller='admin/auth_settings', action='auth_settings', conditions=dict(method=["POST"])) + rmap.connect('auth_home', '%s/auth' % ADMIN_PREFIX, + controller='admin/auth_settings') - rmap.connect('ldap_home', '%s/ldap' % ADMIN_PREFIX, - controller='admin/ldap_settings') - - #ADMIN SETTINGS REST ROUTES + #ADMIN SETTINGS ROUTES with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='admin/settings') as m: m.connect("admin_settings", "/settings", - action="create", conditions=dict(method=["POST"])) + action="settings_vcs", conditions=dict(method=["POST"])) m.connect("admin_settings", "/settings", - action="index", conditions=dict(method=["GET"])) - m.connect("formatted_admin_settings", "/settings.{format}", - action="index", conditions=dict(method=["GET"])) - m.connect("admin_new_setting", "/settings/new", - action="new", conditions=dict(method=["GET"])) - m.connect("formatted_admin_new_setting", "/settings/new.{format}", - action="new", conditions=dict(method=["GET"])) - m.connect("/settings/{setting_id}", - action="update", conditions=dict(method=["PUT"])) - m.connect("/settings/{setting_id}", - action="delete", conditions=dict(method=["DELETE"])) - m.connect("admin_edit_setting", "/settings/{setting_id}/edit", - action="edit", conditions=dict(method=["GET"])) - m.connect("formatted_admin_edit_setting", - "/settings/{setting_id}.{format}/edit", - action="edit", conditions=dict(method=["GET"])) - m.connect("admin_setting", "/settings/{setting_id}", - action="show", conditions=dict(method=["GET"])) - m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}", - action="show", conditions=dict(method=["GET"])) - m.connect("admin_settings_my_account", "/my_account", + action="settings_vcs", conditions=dict(method=["GET"])) + + m.connect("admin_settings_mapping", "/settings/mapping", + action="settings_mapping", conditions=dict(method=["POST"])) + m.connect("admin_settings_mapping", "/settings/mapping", + action="settings_mapping", conditions=dict(method=["GET"])) + + m.connect("admin_settings_global", "/settings/global", + action="settings_global", conditions=dict(method=["POST"])) + m.connect("admin_settings_global", "/settings/global", + action="settings_global", conditions=dict(method=["GET"])) + + m.connect("admin_settings_visual", "/settings/visual", + action="settings_visual", conditions=dict(method=["POST"])) + m.connect("admin_settings_visual", "/settings/visual", + action="settings_visual", conditions=dict(method=["GET"])) + + m.connect("admin_settings_email", "/settings/email", + action="settings_email", conditions=dict(method=["POST"])) + m.connect("admin_settings_email", "/settings/email", + action="settings_email", conditions=dict(method=["GET"])) + + m.connect("admin_settings_hooks", "/settings/hooks", + action="settings_hooks", conditions=dict(method=["POST"])) + m.connect("admin_settings_hooks", "/settings/hooks", + action="settings_hooks", conditions=dict(method=["DELETE"])) + m.connect("admin_settings_hooks", "/settings/hooks", + action="settings_hooks", conditions=dict(method=["GET"])) + + m.connect("admin_settings_search", "/settings/search", + action="settings_search", conditions=dict(method=["POST"])) + m.connect("admin_settings_search", "/settings/search", + action="settings_search", conditions=dict(method=["GET"])) + + m.connect("admin_settings_system", "/settings/system", + action="settings_system", conditions=dict(method=["POST"])) + m.connect("admin_settings_system", "/settings/system", + action="settings_system", conditions=dict(method=["GET"])) + m.connect("admin_settings_system_update", "/settings/system/updates", + action="settings_system_update", conditions=dict(method=["GET"])) + + #ADMIN MY ACCOUNT + with rmap.submapper(path_prefix=ADMIN_PREFIX, + controller='admin/my_account') as m: + + m.connect("my_account", "/my_account", action="my_account", conditions=dict(method=["GET"])) - m.connect("admin_settings_my_account_update", "/my_account_update", - action="my_account_update", conditions=dict(method=["PUT"])) - m.connect("admin_settings_my_repos", "/my_account/repos", - action="my_account_my_repos", conditions=dict(method=["GET"])) - m.connect("admin_settings_my_pullrequests", "/my_account/pull_requests", - action="my_account_my_pullrequests", conditions=dict(method=["GET"])) + m.connect("my_account", "/my_account", + action="my_account", conditions=dict(method=["POST"])) + + m.connect("my_account_password", "/my_account/password", + action="my_account_password", conditions=dict(method=["GET"])) + m.connect("my_account_password", "/my_account/password", + action="my_account_password", conditions=dict(method=["POST"])) + + m.connect("my_account_repos", "/my_account/repos", + action="my_account_repos", conditions=dict(method=["GET"])) + + m.connect("my_account_watched", "/my_account/watched", + action="my_account_watched", conditions=dict(method=["GET"])) + + m.connect("my_account_pullrequests", "/my_account/pull_requests", + action="my_account_pullrequests", conditions=dict(method=["GET"])) + + m.connect("my_account_perms", "/my_account/perms", + action="my_account_perms", conditions=dict(method=["GET"])) + + m.connect("my_account_emails", "/my_account/emails", + action="my_account_emails", conditions=dict(method=["GET"])) + m.connect("my_account_emails", "/my_account/emails", + action="my_account_emails_add", conditions=dict(method=["POST"])) + m.connect("my_account_emails", "/my_account/emails", + action="my_account_emails_delete", conditions=dict(method=["DELETE"])) + + m.connect("my_account_api_keys", "/my_account/api_keys", + action="my_account_api_keys", conditions=dict(method=["GET"])) + m.connect("my_account_api_keys", "/my_account/api_keys", + action="my_account_api_keys_add", conditions=dict(method=["POST"])) + m.connect("my_account_api_keys", "/my_account/api_keys", + action="my_account_api_keys_delete", conditions=dict(method=["DELETE"])) #NOTIFICATION REST ROUTES with rmap.submapper(path_prefix=ADMIN_PREFIX, @@ -390,24 +425,28 @@ def make_map(config): action="index", conditions=dict(method=["GET"])) m.connect("new_gist", "/gists/new", action="new", conditions=dict(method=["GET"])) - m.connect("formatted_new_gist", "/gists/new.{format}", - action="new", conditions=dict(method=["GET"])) - m.connect("formatted_gists", "/gists.{format}", - action="index", conditions=dict(method=["GET"])) + + m.connect("/gists/{gist_id}", action="update", conditions=dict(method=["PUT"])) m.connect("/gists/{gist_id}", action="delete", conditions=dict(method=["DELETE"])) m.connect("edit_gist", "/gists/{gist_id}/edit", - action="edit", conditions=dict(method=["GET"])) - m.connect("formatted_edit_gist", - "/gists/{gist_id}/{format}/edit", - action="edit", conditions=dict(method=["GET"])) + action="edit", conditions=dict(method=["GET", "POST"])) + m.connect("edit_gist_check_revision", "/gists/{gist_id}/edit/check_revision", + action="check_revision", conditions=dict(method=["POST"])) + + m.connect("gist", "/gists/{gist_id}", action="show", conditions=dict(method=["GET"])) - m.connect("formatted_gist", "/gists/{gist_id}/{format}", + m.connect("gist_rev", "/gists/{gist_id}/{revision}", + revision="tip", action="show", conditions=dict(method=["GET"])) - m.connect("formatted_gist_file", "/gists/{gist_id}/{format}/{revision}/{f_path:.*}", + m.connect("formatted_gist", "/gists/{gist_id}/{revision}/{format}", + revision="tip", + action="show", conditions=dict(method=["GET"])) + m.connect("formatted_gist_file", "/gists/{gist_id}/{revision}/{format}/{f_path:.*}", + revision='tip', action="show", conditions=dict(method=["GET"])) #ADMIN MAIN PAGES @@ -489,32 +528,109 @@ def make_map(config): #========================================================================== # REPOSITORY ROUTES #========================================================================== + rmap.connect('repo_creating_home', '/{repo_name:.*?}/repo_creating', + controller='admin/repos', action='repo_creating') + rmap.connect('repo_check_home', '/{repo_name:.*?}/crepo_check', + controller='admin/repos', action='repo_check') + rmap.connect('summary_home', '/{repo_name:.*?}', controller='summary', conditions=dict(function=check_repo)) + # must be here for proper group/repo catching + rmap.connect('repos_group_home', '/{group_name:.*}', + controller='admin/repo_groups', action="show_by_name", + conditions=dict(function=check_group)) + rmap.connect('repo_stats_home', '/{repo_name:.*?}/statistics', + controller='summary', action='statistics', + conditions=dict(function=check_repo)) + rmap.connect('repo_size', '/{repo_name:.*?}/repo_size', controller='summary', action='repo_size', conditions=dict(function=check_repo)) - rmap.connect('repos_group_home', '/{group_name:.*}', - controller='admin/repos_groups', action="show_by_name", - conditions=dict(function=check_group)) + rmap.connect('branch_tag_switcher', '/{repo_name:.*?}/branches-tags', + controller='home', action='branch_tag_switcher') + rmap.connect('repo_refs_data', '/{repo_name:.*?}/refs-data', + controller='home', action='repo_refs_data') rmap.connect('changeset_home', '/{repo_name:.*?}/changeset/{revision}', controller='changeset', revision='tip', conditions=dict(function=check_repo)) + rmap.connect('changeset_children', '/{repo_name:.*?}/changeset_children/{revision}', + controller='changeset', revision='tip', action="changeset_children", + conditions=dict(function=check_repo)) + rmap.connect('changeset_parents', '/{repo_name:.*?}/changeset_parents/{revision}', + controller='changeset', revision='tip', action="changeset_parents", + conditions=dict(function=check_repo)) - # no longer user, but kept for routes to work - rmap.connect("_edit_repo", "/{repo_name:.*?}/edit", - controller='admin/repos', action="edit", - conditions=dict(method=["GET"], function=check_repo) - ) - + # repo edit options rmap.connect("edit_repo", "/{repo_name:.*?}/settings", controller='admin/repos', action="edit", - conditions=dict(method=["GET"], function=check_repo) - ) + conditions=dict(method=["GET"], function=check_repo)) + + rmap.connect("edit_repo_perms", "/{repo_name:.*?}/settings/permissions", + controller='admin/repos', action="edit_permissions", + conditions=dict(method=["GET"], function=check_repo)) + rmap.connect("edit_repo_perms_update", "/{repo_name:.*?}/settings/permissions", + controller='admin/repos', action="edit_permissions_update", + conditions=dict(method=["PUT"], function=check_repo)) + rmap.connect("edit_repo_perms_revoke", "/{repo_name:.*?}/settings/permissions", + controller='admin/repos', action="edit_permissions_revoke", + conditions=dict(method=["DELETE"], function=check_repo)) + + rmap.connect("edit_repo_fields", "/{repo_name:.*?}/settings/fields", + controller='admin/repos', action="edit_fields", + conditions=dict(method=["GET"], function=check_repo)) + rmap.connect('create_repo_fields', "/{repo_name:.*?}/settings/fields/new", + controller='admin/repos', action="create_repo_field", + conditions=dict(method=["PUT"], function=check_repo)) + rmap.connect('delete_repo_fields', "/{repo_name:.*?}/settings/fields/{field_id}", + controller='admin/repos', action="delete_repo_field", + conditions=dict(method=["DELETE"], function=check_repo)) + + + rmap.connect("edit_repo_advanced", "/{repo_name:.*?}/settings/advanced", + controller='admin/repos', action="edit_advanced", + conditions=dict(method=["GET"], function=check_repo)) + + rmap.connect("edit_repo_advanced_locking", "/{repo_name:.*?}/settings/advanced/locking", + controller='admin/repos', action="edit_advanced_locking", + conditions=dict(method=["PUT"], function=check_repo)) + rmap.connect('toggle_locking', "/{repo_name:.*?}/settings/advanced/locking_toggle", + controller='admin/repos', action="toggle_locking", + conditions=dict(method=["GET"], function=check_repo)) + + rmap.connect("edit_repo_advanced_journal", "/{repo_name:.*?}/settings/advanced/journal", + controller='admin/repos', action="edit_advanced_journal", + conditions=dict(method=["PUT"], function=check_repo)) + + rmap.connect("edit_repo_advanced_fork", "/{repo_name:.*?}/settings/advanced/fork", + controller='admin/repos', action="edit_advanced_fork", + conditions=dict(method=["PUT"], function=check_repo)) + + + rmap.connect("edit_repo_caches", "/{repo_name:.*?}/settings/caches", + controller='admin/repos', action="edit_caches", + conditions=dict(method=["GET"], function=check_repo)) + rmap.connect("edit_repo_caches", "/{repo_name:.*?}/settings/caches", + controller='admin/repos', action="edit_caches", + conditions=dict(method=["PUT"], function=check_repo)) + + + rmap.connect("edit_repo_remote", "/{repo_name:.*?}/settings/remote", + controller='admin/repos', action="edit_remote", + conditions=dict(method=["GET"], function=check_repo)) + rmap.connect("edit_repo_remote", "/{repo_name:.*?}/settings/remote", + controller='admin/repos', action="edit_remote", + conditions=dict(method=["PUT"], function=check_repo)) + + rmap.connect("edit_repo_statistics", "/{repo_name:.*?}/settings/statistics", + controller='admin/repos', action="edit_statistics", + conditions=dict(method=["GET"], function=check_repo)) + rmap.connect("edit_repo_statistics", "/{repo_name:.*?}/settings/statistics", + controller='admin/repos', action="edit_statistics", + conditions=dict(method=["PUT"], function=check_repo)) #still working url for backward compat. rmap.connect('raw_changeset_home_depraced', @@ -556,9 +672,14 @@ def make_map(config): rmap.connect('changeset_info', '/changeset_info/{repo_name:.*?}/{revision}', controller='changeset', action='changeset_info') + rmap.connect('compare_home', + '/{repo_name:.*?}/compare', + controller='compare', action='index', + conditions=dict(function=check_repo)) + rmap.connect('compare_url', '/{repo_name:.*?}/compare/{org_ref_type}@{org_ref:.*?}...{other_ref_type}@{other_ref:.*?}', - controller='compare', action='index', + controller='compare', action='compare', conditions=dict(function=check_repo), requirements=dict( org_ref_type='(branch|book|tag|rev|__other_ref_type__)', @@ -648,6 +769,11 @@ def make_map(config): controller='files', action='history', revision='tip', f_path='', conditions=dict(function=check_repo)) + rmap.connect('files_authors_home', + '/{repo_name:.*?}/authors/{revision}/{f_path:.*}', + controller='files', action='authors', revision='tip', f_path='', + conditions=dict(function=check_repo)) + rmap.connect('files_diff_home', '/{repo_name:.*?}/diff/{f_path:.*}', controller='files', action='diff', revision='tip', f_path='', conditions=dict(function=check_repo)) @@ -681,6 +807,11 @@ def make_map(config): controller='files', action='add', revision='tip', f_path='', conditions=dict(function=check_repo)) + rmap.connect('files_delete_home', + '/{repo_name:.*?}/delete/{revision}/{f_path:.*}', + controller='files', action='delete', revision='tip', + f_path='', conditions=dict(function=check_repo)) + rmap.connect('files_archive_home', '/{repo_name:.*?}/archive/{fname}', controller='files', action='archivefile', conditions=dict(function=check_repo)) diff --git a/rhodecode/controllers/__init__.py b/kallithea/controllers/__init__.py rename from rhodecode/controllers/__init__.py rename to kallithea/controllers/__init__.py --- a/rhodecode/controllers/__init__.py +++ b/kallithea/controllers/__init__.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . diff --git a/rhodecode/controllers/admin/__init__.py b/kallithea/controllers/admin/__init__.py rename from rhodecode/controllers/admin/__init__.py rename to kallithea/controllers/admin/__init__.py --- a/rhodecode/controllers/admin/__init__.py +++ b/kallithea/controllers/admin/__init__.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . diff --git a/rhodecode/controllers/admin/admin.py b/kallithea/controllers/admin/admin.py rename from rhodecode/controllers/admin/admin.py rename to kallithea/controllers/admin/admin.py --- a/rhodecode/controllers/admin/admin.py +++ b/kallithea/controllers/admin/admin.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.admin.admin - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Controller for Admin panel of Rhodecode - - :created_on: Apr 7, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.admin.admin +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Controller for Admin panel of Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 7, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging @@ -32,12 +35,12 @@ from whoosh.qparser.dateparse import Dat from whoosh import query from sqlalchemy.sql.expression import or_, and_, func -from rhodecode.model.db import UserLog, User -from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator -from rhodecode.lib.base import BaseController, render -from rhodecode.lib.utils2 import safe_int, remove_prefix, remove_suffix -from rhodecode.lib.indexers import JOURNAL_SCHEMA -from rhodecode.lib.helpers import Page +from kallithea.model.db import UserLog, User +from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator +from kallithea.lib.base import BaseController, render +from kallithea.lib.utils2 import safe_int, remove_prefix, remove_suffix +from kallithea.lib.indexers import JOURNAL_SCHEMA +from kallithea.lib.helpers import Page log = logging.getLogger(__name__) diff --git a/kallithea/controllers/admin/auth_settings.py b/kallithea/controllers/admin/auth_settings.py new file mode 100644 --- /dev/null +++ b/kallithea/controllers/admin/auth_settings.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.controllers.admin.auth_settings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +pluggable authentication controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Nov 26, 2010 +:author: akesterson +""" + +import pprint +import logging +import formencode.htmlfill +import traceback + +from pylons import request, response, session, tmpl_context as c, url +from pylons.controllers.util import abort, redirect +from pylons.i18n.translation import _ + +from sqlalchemy.exc import DatabaseError + +from kallithea.lib import helpers as h +from kallithea.lib.compat import json, formatted_json +from kallithea.lib.base import BaseController, render +from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator +from kallithea.lib import auth_modules +from kallithea.model.forms import AuthSettingsForm +from kallithea.model.db import Setting +from kallithea.model.meta import Session + +log = logging.getLogger(__name__) + + +class AuthSettingsController(BaseController): + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + def __before__(self): + super(AuthSettingsController, self).__before__() + + def __load_defaults(self): + c.available_plugins = [ + 'kallithea.lib.auth_modules.auth_internal', + 'kallithea.lib.auth_modules.auth_container', + 'kallithea.lib.auth_modules.auth_ldap', + 'kallithea.lib.auth_modules.auth_crowd', + ] + c.enabled_plugins = Setting.get_auth_plugins() + + def index(self, defaults=None, errors=None, prefix_error=False): + self.__load_defaults() + _defaults = {} + # default plugins loaded + formglobals = { + "auth_plugins": ["kallithea.lib.auth_modules.auth_internal"] + } + formglobals.update(Setting.get_auth_settings()) + formglobals["plugin_settings"] = {} + formglobals["auth_plugins_shortnames"] = {} + _defaults["auth_plugins"] = formglobals["auth_plugins"] + + for module in formglobals["auth_plugins"]: + plugin = auth_modules.loadplugin(module) + plugin_name = plugin.name + formglobals["auth_plugins_shortnames"][module] = plugin_name + formglobals["plugin_settings"][module] = plugin.plugin_settings() + for v in formglobals["plugin_settings"][module]: + fullname = ("auth_" + plugin_name + "_" + v["name"]) + if "default" in v: + _defaults[fullname] = v["default"] + # Current values will be the default on the form, if there are any + setting = Setting.get_by_name(fullname) + if setting: + _defaults[fullname] = setting.app_settings_value + # we want to show , seperated list of enabled plugins + _defaults['auth_plugins'] = ','.join(_defaults['auth_plugins']) + if defaults: + _defaults.update(defaults) + + formglobals["defaults"] = _defaults + # set template context variables + for k, v in formglobals.iteritems(): + setattr(c, k, v) + + log.debug(pprint.pformat(formglobals, indent=4)) + log.debug(formatted_json(defaults)) + return formencode.htmlfill.render( + render('admin/auth/auth_settings.html'), + defaults=_defaults, + errors=errors, + prefix_error=prefix_error, + encoding="UTF-8", + force_defaults=True, + ) + + def auth_settings(self): + """POST create and store auth settings""" + self.__load_defaults() + _form = AuthSettingsForm(c.enabled_plugins)() + log.debug("POST Result: %s" % formatted_json(dict(request.POST))) + + try: + form_result = _form.to_python(dict(request.POST)) + for k, v in form_result.items(): + if k == 'auth_plugins': + # we want to store it comma separated inside our settings + v = ','.join(v) + log.debug("%s = %s" % (k, str(v))) + setting = Setting.create_or_update(k, v) + Session().add(setting) + Session().commit() + h.flash(_('Auth settings updated successfully'), + category='success') + except formencode.Invalid, errors: + log.error(traceback.format_exc()) + e = errors.error_dict or {} + return self.index( + defaults=errors.value, + errors=e, + prefix_error=False) + except Exception: + log.error(traceback.format_exc()) + h.flash(_('error occurred during update of auth settings'), + category='error') + + return redirect(url('auth_home')) diff --git a/rhodecode/controllers/admin/defaults.py b/kallithea/controllers/admin/defaults.py rename from rhodecode/controllers/admin/defaults.py rename to kallithea/controllers/admin/defaults.py --- a/rhodecode/controllers/admin/defaults.py +++ b/kallithea/controllers/admin/defaults.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.admin.defaults - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - default settings controller for Rhodecode - - :created_on: Apr 27, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.admin.defaults +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +default settings controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 27, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import logging import traceback @@ -32,13 +34,13 @@ from pylons import request, session, tmp from pylons.controllers.util import abort, redirect from pylons.i18n.translation import _ -from rhodecode.lib import helpers as h -from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator -from rhodecode.lib.base import BaseController, render -from rhodecode.model.forms import DefaultsForm -from rhodecode.model.meta import Session -from rhodecode import BACKENDS -from rhodecode.model.db import RhodeCodeSetting +from kallithea.lib import helpers as h +from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator +from kallithea.lib.base import BaseController, render +from kallithea.model.forms import DefaultsForm +from kallithea.model.meta import Session +from kallithea import BACKENDS +from kallithea.model.db import Setting log = logging.getLogger(__name__) @@ -58,7 +60,7 @@ class DefaultsController(BaseController) """GET /defaults: All items in the collection""" # url('defaults') c.backends = BACKENDS.keys() - defaults = RhodeCodeSetting.get_default_repo_settings() + defaults = Setting.get_default_repo_settings() return htmlfill.render( render('admin/defaults/defaults.html'), @@ -89,8 +91,7 @@ class DefaultsController(BaseController) try: form_result = _form.to_python(dict(request.POST)) for k, v in form_result.iteritems(): - setting = RhodeCodeSetting.get_by_name_or_create(k) - setting.app_settings_value = v + setting = Setting.create_or_update(k, v) Session().add(setting) Session().commit() h.flash(_('Default settings updated successfully'), diff --git a/rhodecode/controllers/admin/gists.py b/kallithea/controllers/admin/gists.py rename from rhodecode/controllers/admin/gists.py rename to kallithea/controllers/admin/gists.py --- a/rhodecode/controllers/admin/gists.py +++ b/kallithea/controllers/admin/gists.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.admin.gist - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - gist controller for RhodeCode - - :created_on: May 9, 2013 - :author: marcink - :copyright: (C) 2010-2013 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.admin.gist +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +gist controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: May 9, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import time import logging import traceback @@ -32,18 +35,19 @@ from pylons import request, response, tm from pylons.controllers.util import abort, redirect from pylons.i18n.translation import _ -from rhodecode.model.forms import GistForm -from rhodecode.model.gist import GistModel -from rhodecode.model.meta import Session -from rhodecode.model.db import Gist -from rhodecode.lib import helpers as h -from rhodecode.lib.base import BaseController, render -from rhodecode.lib.auth import LoginRequired, NotAnonymous -from rhodecode.lib.utils2 import safe_str, safe_int, time_to_datetime -from rhodecode.lib.helpers import Page +from kallithea.model.forms import GistForm +from kallithea.model.gist import GistModel +from kallithea.model.meta import Session +from kallithea.model.db import Gist, User +from kallithea.lib import helpers as h +from kallithea.lib.base import BaseController, render +from kallithea.lib.auth import LoginRequired, NotAnonymous +from kallithea.lib.utils import jsonify +from kallithea.lib.utils2 import safe_str, safe_int, time_to_datetime +from kallithea.lib.helpers import Page from webob.exc import HTTPNotFound, HTTPForbidden from sqlalchemy.sql.expression import or_ -from rhodecode.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.exceptions import VCSError, NodeNotChangedError log = logging.getLogger(__name__) @@ -51,7 +55,7 @@ log = logging.getLogger(__name__) class GistsController(BaseController): """REST Controller styled on the Atom Publishing Protocol""" - def __load_defaults(self): + def __load_defaults(self, extra_values=None): c.lifetime_values = [ (str(-1), _('forever')), (str(5), _('5 minutes')), @@ -59,27 +63,42 @@ class GistsController(BaseController): (str(60 * 24), _('1 day')), (str(60 * 24 * 30), _('1 month')), ] + if extra_values: + c.lifetime_values.append(extra_values) c.lifetime_options = [(c.lifetime_values, _("Lifetime"))] @LoginRequired() - def index(self, format='html'): + def index(self): """GET /admin/gists: All items in the collection""" # url('gists') - c.show_private = request.GET.get('private') and c.rhodecode_user.username != 'default' - c.show_public = request.GET.get('public') and c.rhodecode_user.username != 'default' + not_default_user = c.authuser.username != User.DEFAULT_USER + c.show_private = request.GET.get('private') and not_default_user + c.show_public = request.GET.get('public') and not_default_user gists = Gist().query()\ .filter(or_(Gist.gist_expires == -1, Gist.gist_expires >= time.time()))\ .order_by(Gist.created_on.desc()) - if c.show_private: - c.gists = gists.filter(Gist.gist_type == Gist.GIST_PRIVATE)\ - .filter(Gist.gist_owner == c.rhodecode_user.user_id) - elif c.show_public: - c.gists = gists.filter(Gist.gist_type == Gist.GIST_PUBLIC)\ - .filter(Gist.gist_owner == c.rhodecode_user.user_id) + + # MY private + if c.show_private and not c.show_public: + gists = gists.filter(Gist.gist_type == Gist.GIST_PRIVATE)\ + .filter(Gist.gist_owner == c.authuser.user_id) + # MY public + elif c.show_public and not c.show_private: + gists = gists.filter(Gist.gist_type == Gist.GIST_PUBLIC)\ + .filter(Gist.gist_owner == c.authuser.user_id) - else: - c.gists = gists.filter(Gist.gist_type == Gist.GIST_PUBLIC) + # MY public+private + elif c.show_private and c.show_public: + gists = gists.filter(or_(Gist.gist_type == Gist.GIST_PUBLIC, + Gist.gist_type == Gist.GIST_PRIVATE))\ + .filter(Gist.gist_owner == c.authuser.user_id) + + # default show ALL public gists + if not c.show_public and not c.show_private: + gists = gists.filter(Gist.gist_type == Gist.GIST_PUBLIC) + + c.gists = gists p = safe_int(request.GET.get('page', 1), 1) c.gists_pager = Page(c.gists, page=p, items_per_page=10) return render('admin/gists/index.html') @@ -94,7 +113,7 @@ class GistsController(BaseController): try: form_result = gist_form.to_python(dict(request.POST)) #TODO: multiple files support, from the form - filename = form_result['filename'] or 'gistfile1.txt' + filename = form_result['filename'] or Gist.DEFAULT_FILENAME nodes = { filename: { 'content': form_result['content'], @@ -105,7 +124,7 @@ class GistsController(BaseController): gist_type = Gist.GIST_PUBLIC if _public else Gist.GIST_PRIVATE gist = GistModel().create( description=form_result['description'], - owner=c.rhodecode_user, + owner=c.authuser.user_id, gist_mapping=nodes, gist_type=gist_type, lifetime=form_result['lifetime'] @@ -159,7 +178,7 @@ class GistsController(BaseController): # method='delete') # url('gist', gist_id=ID) gist = GistModel().get_gist(gist_id) - owner = gist.gist_owner == c.rhodecode_user.user_id + owner = gist.gist_owner == c.authuser.user_id if h.HasPermissionAny('hg.admin')() or owner: GistModel().delete(gist) Session().commit() @@ -170,7 +189,7 @@ class GistsController(BaseController): return redirect(url('gists')) @LoginRequired() - def show(self, gist_id, format='html', revision='tip', f_path=None): + def show(self, gist_id, revision='tip', format='html', f_path=None): """GET /admin/gists/gist_id: Show a specific item""" # url('gist', gist_id=ID) c.gist = Gist.get_or_404(gist_id) @@ -182,7 +201,8 @@ class GistsController(BaseController): (time_to_datetime(c.gist.gist_expires))) raise HTTPNotFound() try: - c.file_changeset, c.files = GistModel().get_gist_files(gist_id) + c.file_changeset, c.files = GistModel().get_gist_files(gist_id, + revision=revision) except VCSError: log.error(traceback.format_exc()) raise HTTPNotFound() @@ -197,3 +217,78 @@ class GistsController(BaseController): def edit(self, gist_id, format='html'): """GET /admin/gists/gist_id/edit: Form to edit an existing item""" # url('edit_gist', gist_id=ID) + c.gist = Gist.get_or_404(gist_id) + + #check if this gist is not expired + if c.gist.gist_expires != -1: + if time.time() > c.gist.gist_expires: + log.error('Gist expired at %s' % + (time_to_datetime(c.gist.gist_expires))) + raise HTTPNotFound() + try: + c.file_changeset, c.files = GistModel().get_gist_files(gist_id) + except VCSError: + log.error(traceback.format_exc()) + raise HTTPNotFound() + + self.__load_defaults(extra_values=('0', _('unmodified'))) + rendered = render('admin/gists/edit.html') + + if request.POST: + rpost = request.POST + nodes = {} + for org_filename, filename, mimetype, content in zip( + rpost.getall('org_files'), + rpost.getall('files'), + rpost.getall('mimetypes'), + rpost.getall('contents')): + + nodes[org_filename] = { + 'org_filename': org_filename, + 'filename': filename, + 'content': content, + 'lexer': mimetype, + } + try: + GistModel().update( + gist=c.gist, + description=rpost['description'], + owner=c.gist.owner, + gist_mapping=nodes, + gist_type=c.gist.gist_type, + lifetime=rpost['lifetime'] + ) + + Session().commit() + h.flash(_('Successfully updated gist content'), category='success') + except NodeNotChangedError: + # raised if nothing was changed in repo itself. We anyway then + # store only DB stuff for gist + Session().commit() + h.flash(_('Successfully updated gist data'), category='success') + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during update of gist %s') % gist_id, + category='error') + + return redirect(url('gist', gist_id=gist_id)) + + return rendered + + @LoginRequired() + @NotAnonymous() + @jsonify + def check_revision(self, gist_id): + c.gist = Gist.get_or_404(gist_id) + last_rev = c.gist.scm_instance.get_changeset() + success = True + revision = request.POST.get('revision') + + ##TODO: maybe move this to model ? + if revision != last_rev.raw_id: + log.error('Last revision %s is different then submited %s' + % (revision, last_rev)) + # our gist has newer version than we + success = False + + return {'success': success} diff --git a/kallithea/controllers/admin/my_account.py b/kallithea/controllers/admin/my_account.py new file mode 100644 --- /dev/null +++ b/kallithea/controllers/admin/my_account.py @@ -0,0 +1,294 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.controllers.admin.my_account +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +my account controller for Kallithea admin + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: August 20, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import time +import logging +import traceback +import formencode + +from sqlalchemy import func, or_ +from formencode import htmlfill +from pylons import request, tmpl_context as c, url +from pylons.controllers.util import redirect +from pylons.i18n.translation import _ + +from kallithea import EXTERN_TYPE_INTERNAL +from kallithea.lib import helpers as h +from kallithea.lib.auth import LoginRequired, NotAnonymous, AuthUser +from kallithea.lib.base import BaseController, render +from kallithea.lib.utils2 import generate_api_key, safe_int +from kallithea.lib.compat import json +from kallithea.model.db import Repository, PullRequest, PullRequestReviewers, \ + UserEmailMap, UserApiKeys, User, UserFollowing +from kallithea.model.forms import UserForm, PasswordChangeForm +from kallithea.model.user import UserModel +from kallithea.model.repo import RepoModel +from kallithea.model.api_key import ApiKeyModel +from kallithea.model.meta import Session + +log = logging.getLogger(__name__) + + +class MyAccountController(BaseController): + """REST Controller styled on the Atom Publishing Protocol""" + # To properly map this controller, ensure your config/routing.py + # file has a resource setup: + # map.resource('setting', 'settings', controller='admin/settings', + # path_prefix='/admin', name_prefix='admin_') + + @LoginRequired() + @NotAnonymous() + def __before__(self): + super(MyAccountController, self).__before__() + + def __load_data(self): + c.user = User.get(self.authuser.user_id) + if c.user.username == User.DEFAULT_USER: + h.flash(_("You can't edit this user since it's" + " crucial for entire application"), category='warning') + return redirect(url('users')) + c.EXTERN_TYPE_INTERNAL = EXTERN_TYPE_INTERNAL + + def _load_my_repos_data(self, watched=False): + if watched: + admin = False + repos_list = [x.follows_repository for x in + Session().query(UserFollowing).filter( + UserFollowing.user_id == + self.authuser.user_id).all()] + else: + admin = True + repos_list = Session().query(Repository)\ + .filter(Repository.user_id == + self.authuser.user_id)\ + .order_by(func.lower(Repository.repo_name)).all() + + repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, + admin=admin) + #json used to render the grid + return json.dumps(repos_data) + + def my_account(self): + """ + GET /_admin/my_account Displays info about my account + """ + # url('my_account') + c.active = 'profile' + self.__load_data() + c.perm_user = AuthUser(user_id=self.authuser.user_id, + ip_addr=self.ip_addr) + c.extern_type = c.user.extern_type + c.extern_name = c.user.extern_name + + defaults = c.user.get_dict() + update = False + if request.POST: + _form = UserForm(edit=True, + old_data={'user_id': self.authuser.user_id, + 'email': self.authuser.email})() + form_result = {} + try: + post_data = dict(request.POST) + post_data['new_password'] = '' + post_data['password_confirmation'] = '' + form_result = _form.to_python(post_data) + # skip updating those attrs for my account + skip_attrs = ['admin', 'active', 'extern_type', 'extern_name', + 'new_password', 'password_confirmation'] + #TODO: plugin should define if username can be updated + if c.extern_type != EXTERN_TYPE_INTERNAL: + # forbid updating username for external accounts + skip_attrs.append('username') + + UserModel().update(self.authuser.user_id, form_result, + skip_attrs=skip_attrs) + h.flash(_('Your account was updated successfully'), + category='success') + Session().commit() + update = True + + except formencode.Invalid, errors: + return htmlfill.render( + render('admin/my_account/my_account.html'), + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8") + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during update of user %s') \ + % form_result.get('username'), category='error') + if update: + return redirect('my_account') + return htmlfill.render( + render('admin/my_account/my_account.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False + ) + + def my_account_password(self): + c.active = 'password' + self.__load_data() + if request.POST: + _form = PasswordChangeForm(self.authuser.username)() + try: + form_result = _form.to_python(request.POST) + UserModel().update(self.authuser.user_id, form_result) + Session().commit() + h.flash(_("Successfully updated password"), category='success') + except formencode.Invalid as errors: + return htmlfill.render( + render('admin/my_account/my_account.html'), + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8") + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during update of user password'), + category='error') + return render('admin/my_account/my_account.html') + + def my_account_repos(self): + c.active = 'repos' + self.__load_data() + + #json used to render the grid + c.data = self._load_my_repos_data() + return render('admin/my_account/my_account.html') + + def my_account_watched(self): + c.active = 'watched' + self.__load_data() + + #json used to render the grid + c.data = self._load_my_repos_data(watched=True) + return render('admin/my_account/my_account.html') + + def my_account_perms(self): + c.active = 'perms' + self.__load_data() + c.perm_user = AuthUser(user_id=self.authuser.user_id, + ip_addr=self.ip_addr) + + return render('admin/my_account/my_account.html') + + def my_account_emails(self): + c.active = 'emails' + self.__load_data() + + c.user_email_map = UserEmailMap.query()\ + .filter(UserEmailMap.user == c.user).all() + return render('admin/my_account/my_account.html') + + def my_account_emails_add(self): + email = request.POST.get('new_email') + + try: + UserModel().add_extra_email(self.authuser.user_id, email) + Session().commit() + h.flash(_("Added email %s to user") % email, category='success') + except formencode.Invalid, error: + msg = error.error_dict['email'] + h.flash(msg, category='error') + except Exception: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during email saving'), + category='error') + return redirect(url('my_account_emails')) + + def my_account_emails_delete(self): + email_id = request.POST.get('del_email_id') + user_model = UserModel() + user_model.delete_extra_email(self.authuser.user_id, email_id) + Session().commit() + h.flash(_("Removed email from user"), category='success') + return redirect(url('my_account_emails')) + + def my_account_pullrequests(self): + c.active = 'pullrequests' + self.__load_data() + c.show_closed = request.GET.get('pr_show_closed') + + def _filter(pr): + s = sorted(pr, key=lambda o: o.created_on, reverse=True) + if not c.show_closed: + s = filter(lambda p: p.status != PullRequest.STATUS_CLOSED, s) + return s + + c.my_pull_requests = _filter(PullRequest.query()\ + .filter(PullRequest.user_id == + self.authuser.user_id)\ + .all()) + my_prs = [x.pull_request for x in PullRequestReviewers.query() + .filter(PullRequestReviewers.user_id == + self.authuser.user_id).all()] + c.participate_in_pull_requests = _filter(my_prs) + return render('admin/my_account/my_account.html') + + def my_account_api_keys(self): + c.active = 'api_keys' + self.__load_data() + show_expired = True + c.lifetime_values = [ + (str(-1), _('forever')), + (str(5), _('5 minutes')), + (str(60), _('1 hour')), + (str(60 * 24), _('1 day')), + (str(60 * 24 * 30), _('1 month')), + ] + c.lifetime_options = [(c.lifetime_values, _("Lifetime"))] + c.user_api_keys = ApiKeyModel().get_api_keys(self.authuser.user_id, + show_expired=show_expired) + return render('admin/my_account/my_account.html') + + def my_account_api_keys_add(self): + lifetime = safe_int(request.POST.get('lifetime'), -1) + description = request.POST.get('description') + new_api_key = ApiKeyModel().create(self.authuser.user_id, + description, lifetime) + Session().commit() + h.flash(_("Api key successfully created"), category='success') + return redirect(url('my_account_api_keys')) + + def my_account_api_keys_delete(self): + api_key = request.POST.get('del_api_key') + user_id = self.authuser.user_id + if request.POST.get('del_api_key_builtin'): + user = User.get(user_id) + if user: + user.api_key = generate_api_key(user.username) + Session().add(user) + Session().commit() + h.flash(_("Api key successfully reset"), category='success') + elif api_key: + ApiKeyModel().delete(api_key, self.authuser.user_id) + Session().commit() + h.flash(_("Api key successfully deleted"), category='success') + + return redirect(url('my_account_api_keys')) diff --git a/rhodecode/controllers/admin/notifications.py b/kallithea/controllers/admin/notifications.py rename from rhodecode/controllers/admin/notifications.py rename to kallithea/controllers/admin/notifications.py --- a/rhodecode/controllers/admin/notifications.py +++ b/kallithea/controllers/admin/notifications.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.admin.notifications - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - notifications controller for RhodeCode - - :created_on: Nov 23, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.admin.notifications +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +notifications controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Nov 23, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import logging import traceback @@ -29,15 +31,16 @@ import traceback from pylons import request from pylons import tmpl_context as c, url from pylons.controllers.util import redirect, abort +from webob.exc import HTTPBadRequest -from rhodecode.model.db import Notification -from rhodecode.model.notification import NotificationModel -from rhodecode.model.meta import Session -from rhodecode.lib.auth import LoginRequired, NotAnonymous -from rhodecode.lib.base import BaseController, render -from rhodecode.lib import helpers as h -from rhodecode.lib.helpers import Page -from rhodecode.lib.utils2 import safe_int +from kallithea.model.db import Notification +from kallithea.model.notification import NotificationModel +from kallithea.model.meta import Session +from kallithea.lib.auth import LoginRequired, NotAnonymous +from kallithea.lib.base import BaseController, render +from kallithea.lib import helpers as h +from kallithea.lib.helpers import Page +from kallithea.lib.utils2 import safe_int log = logging.getLogger(__name__) @@ -58,8 +61,8 @@ class NotificationsController(BaseContro def index(self, format='html'): """GET /_admin/notifications: All items in the collection""" # url('notifications') - c.user = self.rhodecode_user - notif = NotificationModel().get_for_user(self.rhodecode_user.user_id, + c.user = self.authuser + notif = NotificationModel().get_for_user(self.authuser.user_id, filter_=request.GET.getall('type')) p = safe_int(request.GET.get('page', 1), 1) @@ -81,11 +84,11 @@ class NotificationsController(BaseContro if request.environ.get('HTTP_X_PARTIAL_XHR'): nm = NotificationModel() # mark all read - nm.mark_all_read_for_user(self.rhodecode_user.user_id, + nm.mark_all_read_for_user(self.authuser.user_id, filter_=request.GET.getall('type')) Session().commit() - c.user = self.rhodecode_user - notif = nm.get_for_user(self.rhodecode_user.user_id, + c.user = self.authuser + notif = nm.get_for_user(self.authuser.user_id, filter_=request.GET.getall('type')) c.notifications = Page(notif, page=1, items_per_page=10) return render('admin/notifications/notifications_data.html') @@ -108,16 +111,17 @@ class NotificationsController(BaseContro # url('notification', notification_id=ID) try: no = Notification.get(notification_id) - owner = all(un.user.user_id == c.rhodecode_user.user_id + owner = all(un.user.user_id == c.authuser.user_id for un in no.notifications_to_users) if h.HasPermissionAny('hg.admin')() or owner: - NotificationModel().mark_read(c.rhodecode_user.user_id, no) - Session().commit() - return 'ok' + # deletes only notification2user + NotificationModel().mark_read(c.authuser.user_id, no) + Session().commit() + return 'ok' except Exception: Session().rollback() log.error(traceback.format_exc()) - return 'fail' + raise HTTPBadRequest() def delete(self, notification_id): """DELETE /_admin/notifications/id: Delete an existing item""" @@ -127,30 +131,30 @@ class NotificationsController(BaseContro # h.form(url('notification', notification_id=ID), # method='delete') # url('notification', notification_id=ID) - try: no = Notification.get(notification_id) - owner = all(un.user.user_id == c.rhodecode_user.user_id + owner = any(un.user.user_id == c.authuser.user_id for un in no.notifications_to_users) if h.HasPermissionAny('hg.admin')() or owner: - NotificationModel().delete(c.rhodecode_user.user_id, no) - Session().commit() - return 'ok' + # deletes only notification2user + NotificationModel().delete(c.authuser.user_id, no) + Session().commit() + return 'ok' except Exception: Session().rollback() log.error(traceback.format_exc()) - return 'fail' + raise HTTPBadRequest() def show(self, notification_id, format='html'): """GET /_admin/notifications/id: Show a specific item""" # url('notification', notification_id=ID) - c.user = self.rhodecode_user + c.user = self.authuser no = Notification.get(notification_id) - owner = any(un.user.user_id == c.rhodecode_user.user_id + owner = any(un.user.user_id == c.authuser.user_id for un in no.notifications_to_users) - - if no and (h.HasPermissionAny('hg.admin', 'repository.admin')() or owner): + repo_admin = h.HasRepoPermissionAny('repository.admin') + if no and (h.HasPermissionAny('hg.admin')() or repo_admin or owner): unotification = NotificationModel()\ .get_user_notification(c.user.user_id, no) diff --git a/rhodecode/controllers/admin/permissions.py b/kallithea/controllers/admin/permissions.py rename from rhodecode/controllers/admin/permissions.py rename to kallithea/controllers/admin/permissions.py --- a/rhodecode/controllers/admin/permissions.py +++ b/kallithea/controllers/admin/permissions.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.admin.permissions - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - permissions controller for Rhodecode - - :created_on: Apr 27, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.admin.permissions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +permissions controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 27, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import traceback @@ -32,14 +35,14 @@ from pylons import request, session, tmp from pylons.controllers.util import abort, redirect from pylons.i18n.translation import _ -from rhodecode.lib import helpers as h -from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator,\ +from kallithea.lib import helpers as h +from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator,\ AuthUser -from rhodecode.lib.base import BaseController, render -from rhodecode.model.forms import DefaultPermissionsForm -from rhodecode.model.permission import PermissionModel -from rhodecode.model.db import User, UserIpMap, Permission -from rhodecode.model.meta import Session +from kallithea.lib.base import BaseController, render +from kallithea.model.forms import DefaultPermissionsForm +from kallithea.model.permission import PermissionModel +from kallithea.model.db import User, UserIpMap, Permission +from kallithea.model.meta import Session log = logging.getLogger(__name__) @@ -55,6 +58,7 @@ class PermissionsController(BaseControll def __before__(self): super(PermissionsController, self).__before__() + def __load_data(self): c.repo_perms_choices = [('repository.none', _('None'),), ('repository.read', _('Read'),), ('repository.write', _('Write'),), @@ -83,6 +87,11 @@ class PermissionsController(BaseControll c.repo_create_choices = [('hg.create.none', _('Disabled')), ('hg.create.repository', _('Enabled'))] + c.repo_create_on_write_choices = [ + ('hg.create.write_on_repogroup.true', _('Enabled')), + ('hg.create.write_on_repogroup.false', _('Disabled')), + ] + c.user_group_create_choices = [('hg.usergroup.create.false', _('Disabled')), ('hg.usergroup.create.true', _('Enabled'))] @@ -92,50 +101,28 @@ class PermissionsController(BaseControll c.fork_choices = [('hg.fork.none', _('Disabled')), ('hg.fork.repository', _('Enabled'))] - def index(self, format='html'): - """GET /permissions: All items in the collection""" - # url('permissions') - - def create(self): - """POST /permissions: Create a new item""" - # url('permissions') - - def new(self, format='html'): - """GET /permissions/new: Form to create a new item""" - # url('new_permission') - - def update(self, id): - """PUT /permissions/id: Update an existing item""" - # Forms posted to this method should contain a hidden field: - # - # Or using helpers: - # h.form(url('permission', id=ID), - # method='put') - # url('permission', id=ID) - if id == 'default': - c.user = default_user = User.get_default_user() - c.perm_user = AuthUser(user_id=default_user.user_id) - c.user_ip_map = UserIpMap.query()\ - .filter(UserIpMap.user == default_user).all() - + def permission_globals(self): + c.active = 'globals' + self.__load_data() + if request.POST: _form = DefaultPermissionsForm( - [x[0] for x in c.repo_perms_choices], - [x[0] for x in c.group_perms_choices], - [x[0] for x in c.user_group_perms_choices], - [x[0] for x in c.repo_create_choices], - [x[0] for x in c.repo_group_create_choices], - [x[0] for x in c.user_group_create_choices], - [x[0] for x in c.fork_choices], - [x[0] for x in c.register_choices], - [x[0] for x in c.extern_activate_choices], - )() + [x[0] for x in c.repo_perms_choices], + [x[0] for x in c.group_perms_choices], + [x[0] for x in c.user_group_perms_choices], + [x[0] for x in c.repo_create_choices], + [x[0] for x in c.repo_create_on_write_choices], + [x[0] for x in c.repo_group_create_choices], + [x[0] for x in c.user_group_create_choices], + [x[0] for x in c.fork_choices], + [x[0] for x in c.register_choices], + [x[0] for x in c.extern_activate_choices])() try: form_result = _form.to_python(dict(request.POST)) - form_result.update({'perm_user_name': id}) + form_result.update({'perm_user_name': 'default'}) PermissionModel().update(form_result) Session().commit() - h.flash(_('Default permissions updated successfully'), + h.flash(_('Global permissions updated successfully'), category='success') except formencode.Invalid, errors: @@ -152,66 +139,58 @@ class PermissionsController(BaseControll h.flash(_('Error occurred during update of permissions'), category='error') - return redirect(url('edit_permission', id=id)) + return redirect(url('admin_permissions')) + + c.user = User.get_default_user() + defaults = {'anonymous': c.user.active} - def delete(self, id): - """DELETE /permissions/id: Delete an existing item""" - # Forms posted to this method should contain a hidden field: - # - # Or using helpers: - # h.form(url('permission', id=ID), - # method='delete') - # url('permission', id=ID) + for p in c.user.user_perms: + if p.permission.permission_name.startswith('repository.'): + defaults['default_repo_perm'] = p.permission.permission_name + + if p.permission.permission_name.startswith('group.'): + defaults['default_group_perm'] = p.permission.permission_name - def show(self, id, format='html'): - """GET /permissions/id: Show a specific item""" - # url('permission', id=ID) - Permission.get_or_404(-1) + if p.permission.permission_name.startswith('usergroup.'): + defaults['default_user_group_perm'] = p.permission.permission_name - def edit(self, id, format='html'): - """GET /permissions/id/edit: Form to edit an existing item""" - #url('edit_permission', id=ID) + if p.permission.permission_name.startswith('hg.create.write_on_repogroup'): + defaults['create_on_write'] = p.permission.permission_name - #this form can only edit default user permissions - if id == 'default': - c.user = User.get_default_user() - defaults = {'anonymous': c.user.active} - c.perm_user = c.user.AuthUser - c.user_ip_map = UserIpMap.query()\ - .filter(UserIpMap.user == c.user).all() - for p in c.user.user_perms: - if p.permission.permission_name.startswith('repository.'): - defaults['default_repo_perm'] = p.permission.permission_name + elif p.permission.permission_name.startswith('hg.create.'): + defaults['default_repo_create'] = p.permission.permission_name + + if p.permission.permission_name.startswith('hg.repogroup.'): + defaults['default_repo_group_create'] = p.permission.permission_name + + if p.permission.permission_name.startswith('hg.usergroup.'): + defaults['default_user_group_create'] = p.permission.permission_name - if p.permission.permission_name.startswith('group.'): - defaults['default_group_perm'] = p.permission.permission_name - - if p.permission.permission_name.startswith('usergroup.'): - defaults['default_user_group_perm'] = p.permission.permission_name + if p.permission.permission_name.startswith('hg.register.'): + defaults['default_register'] = p.permission.permission_name - if p.permission.permission_name.startswith('hg.create.'): - defaults['default_repo_create'] = p.permission.permission_name + if p.permission.permission_name.startswith('hg.extern_activate.'): + defaults['default_extern_activate'] = p.permission.permission_name - if p.permission.permission_name.startswith('hg.repogroup.'): - defaults['default_repo_group_create'] = p.permission.permission_name - - if p.permission.permission_name.startswith('hg.usergroup.'): - defaults['default_user_group_create'] = p.permission.permission_name + if p.permission.permission_name.startswith('hg.fork.'): + defaults['default_fork'] = p.permission.permission_name - if p.permission.permission_name.startswith('hg.register.'): - defaults['default_register'] = p.permission.permission_name - - if p.permission.permission_name.startswith('hg.extern_activate.'): - defaults['default_extern_activate'] = p.permission.permission_name - - if p.permission.permission_name.startswith('hg.fork.'): - defaults['default_fork'] = p.permission.permission_name + return htmlfill.render( + render('admin/permissions/permissions.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) - return htmlfill.render( - render('admin/permissions/permissions.html'), - defaults=defaults, - encoding="UTF-8", - force_defaults=False - ) - else: - return redirect(url('admin_home')) + def permission_ips(self): + c.active = 'ips' + c.user = User.get_default_user() + c.user_ip_map = UserIpMap.query()\ + .filter(UserIpMap.user == c.user).all() + + return render('admin/permissions/permissions.html') + + def permission_perms(self): + c.active = 'perms' + c.user = User.get_default_user() + c.perm_user = c.user.AuthUser + return render('admin/permissions/permissions.html') diff --git a/kallithea/controllers/admin/repo_groups.py b/kallithea/controllers/admin/repo_groups.py new file mode 100644 --- /dev/null +++ b/kallithea/controllers/admin/repo_groups.py @@ -0,0 +1,473 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.controllers.admin.repo_groups +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Repository groups controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Mar 23, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import logging +import traceback +import formencode +import itertools + +from formencode import htmlfill + +from pylons import request, tmpl_context as c, url +from pylons.controllers.util import abort, redirect +from pylons.i18n.translation import _, ungettext + +from sqlalchemy.exc import IntegrityError + +import kallithea +from kallithea.lib import helpers as h +from kallithea.lib.compat import json +from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator,\ + HasRepoGroupPermissionAnyDecorator, HasRepoGroupPermissionAll,\ + HasPermissionAll +from kallithea.lib.base import BaseController, render +from kallithea.model.db import RepoGroup, Repository +from kallithea.model.scm import RepoGroupList +from kallithea.model.repo_group import RepoGroupModel +from kallithea.model.forms import RepoGroupForm, RepoGroupPermsForm +from kallithea.model.meta import Session +from kallithea.model.repo import RepoModel +from webob.exc import HTTPInternalServerError, HTTPNotFound +from kallithea.lib.utils2 import str2bool, safe_int +from sqlalchemy.sql.expression import func + + +log = logging.getLogger(__name__) + + +class RepoGroupsController(BaseController): + """REST Controller styled on the Atom Publishing Protocol""" + + @LoginRequired() + def __before__(self): + super(RepoGroupsController, self).__before__() + + def __load_defaults(self, allow_empty_group=False, exclude_group_ids=[]): + if HasPermissionAll('hg.admin')('group edit'): + #we're global admin, we're ok and we can create TOP level groups + allow_empty_group = True + + #override the choices for this form, we need to filter choices + #and display only those we have ADMIN right + groups_with_admin_rights = RepoGroupList(RepoGroup.query().all(), + perm_set=['group.admin']) + c.repo_groups = RepoGroup.groups_choices(groups=groups_with_admin_rights, + show_empty_group=allow_empty_group) + # exclude filtered ids + c.repo_groups = filter(lambda x: x[0] not in exclude_group_ids, + c.repo_groups) + c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) + repo_model = RepoModel() + c.users_array = repo_model.get_users_js() + c.user_groups_array = repo_model.get_user_groups_js() + + def __load_data(self, group_id): + """ + Load defaults settings for edit, and update + + :param group_id: + """ + repo_group = RepoGroup.get_or_404(group_id) + data = repo_group.get_dict() + data['group_name'] = repo_group.name + + # fill repository group users + for p in repo_group.repo_group_to_perm: + data.update({'u_perm_%s' % p.user.username: + p.permission.permission_name}) + + # fill repository group groups + for p in repo_group.users_group_to_perm: + data.update({'g_perm_%s' % p.users_group.users_group_name: + p.permission.permission_name}) + + return data + + def _revoke_perms_on_yourself(self, form_result): + _up = filter(lambda u: c.authuser.username == u[0], + form_result['perms_updates']) + _new = filter(lambda u: c.authuser.username == u[0], + form_result['perms_new']) + if _new and _new[0][1] != 'group.admin' or _up and _up[0][1] != 'group.admin': + return True + return False + + def index(self, format='html'): + """GET /repo_groups: All items in the collection""" + # url('repos_groups') + _list = RepoGroup.query()\ + .order_by(func.lower(RepoGroup.group_name))\ + .all() + group_iter = RepoGroupList(_list, perm_set=['group.admin']) + repo_groups_data = [] + total_records = len(group_iter) + _tmpl_lookup = kallithea.CONFIG['pylons.app_globals'].mako_lookup + template = _tmpl_lookup.get_template('data_table/_dt_elements.html') + + repo_group_name = lambda repo_group_name, children_groups: ( + template.get_def("repo_group_name") + .render(repo_group_name, children_groups, _=_, h=h, c=c) + ) + repo_group_actions = lambda repo_group_id, repo_group_name, gr_count: ( + template.get_def("repo_group_actions") + .render(repo_group_id, repo_group_name, gr_count, _=_, h=h, c=c, + ungettext=ungettext) + ) + + for repo_gr in group_iter: + children_groups = map(h.safe_unicode, + itertools.chain((g.name for g in repo_gr.parents), + (x.name for x in [repo_gr]))) + repo_count = repo_gr.repositories.count() + repo_groups_data.append({ + "raw_name": repo_gr.group_name, + "group_name": repo_group_name(repo_gr.group_name, children_groups), + "desc": repo_gr.group_description, + "repos": repo_count, + "owner": h.person(repo_gr.user.username), + "action": repo_group_actions(repo_gr.group_id, repo_gr.group_name, + repo_count) + }) + + c.data = json.dumps({ + "totalRecords": total_records, + "startIndex": 0, + "sort": None, + "dir": "asc", + "records": repo_groups_data + }) + + return render('admin/repo_groups/repo_groups.html') + + def create(self): + """POST /repo_groups: Create a new item""" + # url('repos_groups') + + self.__load_defaults() + + # permissions for can create group based on parent_id are checked + # here in the Form + repo_group_form = RepoGroupForm(available_groups= + map(lambda k: unicode(k[0]), c.repo_groups))() + try: + form_result = repo_group_form.to_python(dict(request.POST)) + RepoGroupModel().create( + group_name=form_result['group_name'], + group_description=form_result['group_description'], + parent=form_result['group_parent_id'], + owner=self.authuser.user_id, + copy_permissions=form_result['group_copy_permissions'] + ) + Session().commit() + h.flash(_('Created repository group %s') \ + % form_result['group_name'], category='success') + #TODO: in futureaction_logger(, '', '', '', self.sa) + except formencode.Invalid, errors: + return htmlfill.render( + render('admin/repo_groups/repo_group_add.html'), + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8") + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during creation of repository group %s') \ + % request.POST.get('group_name'), category='error') + parent_group_id = form_result['group_parent_id'] + #TODO: maybe we should get back to the main view, not the admin one + return redirect(url('repos_groups', parent_group=parent_group_id)) + + def new(self): + """GET /repo_groups/new: Form to create a new item""" + # url('new_repos_group') + if HasPermissionAll('hg.admin')('group create'): + #we're global admin, we're ok and we can create TOP level groups + pass + else: + # we pass in parent group into creation form, thus we know + # what would be the group, we can check perms here ! + group_id = safe_int(request.GET.get('parent_group')) + group = RepoGroup.get(group_id) if group_id else None + group_name = group.group_name if group else None + if HasRepoGroupPermissionAll('group.admin')(group_name, 'group create'): + pass + else: + return abort(403) + + self.__load_defaults() + return render('admin/repo_groups/repo_group_add.html') + + @HasRepoGroupPermissionAnyDecorator('group.admin') + def update(self, group_name): + """PUT /repo_groups/group_name: Update an existing item""" + # Forms posted to this method should contain a hidden field: + # + # Or using helpers: + # h.form(url('repos_group', group_name=GROUP_NAME), + # method='put') + # url('repos_group', group_name=GROUP_NAME) + + c.repo_group = RepoGroupModel()._get_repo_group(group_name) + if HasPermissionAll('hg.admin')('group edit'): + #we're global admin, we're ok and we can create TOP level groups + allow_empty_group = True + elif not c.repo_group.parent_group: + allow_empty_group = True + else: + allow_empty_group = False + self.__load_defaults(allow_empty_group=allow_empty_group, + exclude_group_ids=[c.repo_group.group_id]) + + repo_group_form = RepoGroupForm( + edit=True, + old_data=c.repo_group.get_dict(), + available_groups=c.repo_groups_choices, + can_create_in_root=allow_empty_group, + )() + try: + form_result = repo_group_form.to_python(dict(request.POST)) + + new_gr = RepoGroupModel().update(group_name, form_result) + Session().commit() + h.flash(_('Updated repository group %s') \ + % form_result['group_name'], category='success') + # we now have new name ! + group_name = new_gr.group_name + #TODO: in future action_logger(, '', '', '', self.sa) + except formencode.Invalid, errors: + + return htmlfill.render( + render('admin/repo_groups/repo_group_edit.html'), + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8") + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during update of repository group %s') \ + % request.POST.get('group_name'), category='error') + + return redirect(url('edit_repo_group', group_name=group_name)) + + @HasRepoGroupPermissionAnyDecorator('group.admin') + def delete(self, group_name): + """DELETE /repo_groups/group_name: Delete an existing item""" + # Forms posted to this method should contain a hidden field: + # + # Or using helpers: + # h.form(url('repos_group', group_name=GROUP_NAME), + # method='delete') + # url('repos_group', group_name=GROUP_NAME) + + gr = c.repo_group = RepoGroupModel()._get_repo_group(group_name) + repos = gr.repositories.all() + if repos: + h.flash(_('This group contains %s repositores and cannot be ' + 'deleted') % len(repos), category='warning') + return redirect(url('repos_groups')) + + children = gr.children.all() + if children: + h.flash(_('This group contains %s subgroups and cannot be deleted' + % (len(children))), category='warning') + return redirect(url('repos_groups')) + + try: + RepoGroupModel().delete(group_name) + Session().commit() + h.flash(_('Removed repository group %s') % group_name, + category='success') + #TODO: in future action_logger(, '', '', '', self.sa) + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during deletion of repository group %s') + % group_name, category='error') + + return redirect(url('repos_groups')) + + def show_by_name(self, group_name): + """ + This is a proxy that does a lookup group_name -> id, and shows + the group by id view instead + """ + group_name = group_name.rstrip('/') + id_ = RepoGroup.get_by_group_name(group_name) + if id_: + return self.show(group_name) + raise HTTPNotFound + + @HasRepoGroupPermissionAnyDecorator('group.read', 'group.write', + 'group.admin') + def show(self, group_name): + """GET /repo_groups/group_name: Show a specific item""" + # url('repos_group', group_name=GROUP_NAME) + c.active = 'settings' + + c.group = c.repo_group = RepoGroupModel()._get_repo_group(group_name) + c.group_repos = c.group.repositories.all() + + #overwrite our cached list with current filter + gr_filter = c.group_repos + c.repo_cnt = 0 + + groups = RepoGroup.query().order_by(RepoGroup.group_name)\ + .filter(RepoGroup.group_parent_id == c.group.group_id).all() + c.groups = self.scm_model.get_repo_groups(groups) + + c.repos_list = Repository.query()\ + .filter(Repository.group_id == c.group.group_id)\ + .order_by(func.lower(Repository.repo_name))\ + .all() + + repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list, + admin=False) + #json used to render the grid + c.data = json.dumps(repos_data) + + return render('admin/repo_groups/repo_group_show.html') + + @HasRepoGroupPermissionAnyDecorator('group.admin') + def edit(self, group_name): + """GET /repo_groups/group_name/edit: Form to edit an existing item""" + # url('edit_repo_group', group_name=GROUP_NAME) + c.active = 'settings' + + c.repo_group = RepoGroupModel()._get_repo_group(group_name) + #we can only allow moving empty group if it's already a top-level + #group, ie has no parents, or we're admin + if HasPermissionAll('hg.admin')('group edit'): + #we're global admin, we're ok and we can create TOP level groups + allow_empty_group = True + elif not c.repo_group.parent_group: + allow_empty_group = True + else: + allow_empty_group = False + + self.__load_defaults(allow_empty_group=allow_empty_group, + exclude_group_ids=[c.repo_group.group_id]) + defaults = self.__load_data(c.repo_group.group_id) + + return htmlfill.render( + render('admin/repo_groups/repo_group_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False + ) + + @HasRepoGroupPermissionAnyDecorator('group.admin') + def edit_repo_group_advanced(self, group_name): + """GET /repo_groups/group_name/edit: Form to edit an existing item""" + # url('edit_repo_group', group_name=GROUP_NAME) + c.active = 'advanced' + c.repo_group = RepoGroupModel()._get_repo_group(group_name) + + return render('admin/repo_groups/repo_group_edit.html') + + @HasRepoGroupPermissionAnyDecorator('group.admin') + def edit_repo_group_perms(self, group_name): + """GET /repo_groups/group_name/edit: Form to edit an existing item""" + # url('edit_repo_group', group_name=GROUP_NAME) + c.active = 'perms' + c.repo_group = RepoGroupModel()._get_repo_group(group_name) + self.__load_defaults() + defaults = self.__load_data(c.repo_group.group_id) + + return htmlfill.render( + render('admin/repo_groups/repo_group_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False + ) + + @HasRepoGroupPermissionAnyDecorator('group.admin') + def update_perms(self, group_name): + """ + Update permissions for given repository group + + :param group_name: + """ + + c.repo_group = RepoGroupModel()._get_repo_group(group_name) + valid_recursive_choices = ['none', 'repos', 'groups', 'all'] + form_result = RepoGroupPermsForm(valid_recursive_choices)().to_python(request.POST) + if not c.authuser.is_admin: + if self._revoke_perms_on_yourself(form_result): + msg = _('Cannot revoke permission for yourself as admin') + h.flash(msg, category='warning') + return redirect(url('edit_repo_group_perms', group_name=group_name)) + recursive = form_result['recursive'] + # iterate over all members(if in recursive mode) of this groups and + # set the permissions ! + # this can be potentially heavy operation + RepoGroupModel()._update_permissions(c.repo_group, + form_result['perms_new'], + form_result['perms_updates'], + recursive) + #TODO: implement this + #action_logger(self.authuser, 'admin_changed_repo_permissions', + # repo_name, self.ip_addr, self.sa) + Session().commit() + h.flash(_('Repository Group permissions updated'), category='success') + return redirect(url('edit_repo_group_perms', group_name=group_name)) + + @HasRepoGroupPermissionAnyDecorator('group.admin') + def delete_perms(self, group_name): + """ + DELETE an existing repository group permission user + + :param group_name: + """ + try: + obj_type = request.POST.get('obj_type') + obj_id = None + if obj_type == 'user': + obj_id = safe_int(request.POST.get('user_id')) + elif obj_type == 'user_group': + obj_id = safe_int(request.POST.get('user_group_id')) + + if not c.authuser.is_admin: + if obj_type == 'user' and c.authuser.user_id == obj_id: + msg = _('Cannot revoke permission for yourself as admin') + h.flash(msg, category='warning') + raise Exception('revoke admin permission on self') + recursive = request.POST.get('recursive', 'none') + if obj_type == 'user': + RepoGroupModel().delete_permission(repo_group=group_name, + obj=obj_id, obj_type='user', + recursive=recursive) + elif obj_type == 'user_group': + RepoGroupModel().delete_permission(repo_group=group_name, + obj=obj_id, + obj_type='user_group', + recursive=recursive) + + Session().commit() + except Exception: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during revoking of permission'), + category='error') + raise HTTPInternalServerError() diff --git a/rhodecode/controllers/admin/repos.py b/kallithea/controllers/admin/repos.py rename from rhodecode/controllers/admin/repos.py rename to kallithea/controllers/admin/repos.py --- a/rhodecode/controllers/admin/repos.py +++ b/kallithea/controllers/admin/repos.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.admin.repos - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Repositories controller for RhodeCode - - :created_on: Apr 7, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,36 +11,47 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.admin.repos +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Repositories controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 7, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import logging import traceback import formencode from formencode import htmlfill - -from webob.exc import HTTPInternalServerError, HTTPForbidden -from pylons import request, session, tmpl_context as c, url +from webob.exc import HTTPInternalServerError, HTTPForbidden, HTTPNotFound +from pylons import request, tmpl_context as c, url from pylons.controllers.util import redirect from pylons.i18n.translation import _ -from sqlalchemy.exc import IntegrityError +from sqlalchemy.sql.expression import func -import rhodecode -from rhodecode.lib import helpers as h -from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \ - HasPermissionAnyDecorator, HasRepoPermissionAllDecorator, NotAnonymous,\ - HasPermissionAny, HasReposGroupPermissionAny, HasRepoPermissionAnyDecorator -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.utils import action_logger, repo_name_slug -from rhodecode.lib.helpers import get_token -from rhodecode.model.meta import Session -from rhodecode.model.db import User, Repository, UserFollowing, RepoGroup,\ - RhodeCodeSetting, RepositoryField -from rhodecode.model.forms import RepoForm, RepoFieldForm, RepoPermsForm -from rhodecode.model.scm import ScmModel, RepoGroupList, RepoList -from rhodecode.model.repo import RepoModel -from rhodecode.lib.compat import json -from sqlalchemy.sql.expression import func -from rhodecode.lib.exceptions import AttachedForksError -from rhodecode.lib.utils2 import safe_int +from kallithea.lib import helpers as h +from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator, \ + HasRepoPermissionAllDecorator, NotAnonymous,HasPermissionAny, \ + HasRepoGroupPermissionAny, HasRepoPermissionAnyDecorator +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.utils import action_logger, repo_name_slug, jsonify +from kallithea.lib.helpers import get_token +from kallithea.lib.vcs import RepositoryError +from kallithea.model.meta import Session +from kallithea.model.db import User, Repository, UserFollowing, RepoGroup,\ + Setting, RepositoryField +from kallithea.model.forms import RepoForm, RepoFieldForm, RepoPermsForm +from kallithea.model.scm import ScmModel, RepoGroupList, RepoList +from kallithea.model.repo import RepoModel +from kallithea.lib.compat import json +from kallithea.lib.exceptions import AttachedForksError +from kallithea.lib.utils2 import safe_int log = logging.getLogger(__name__) @@ -67,15 +67,32 @@ class ReposController(BaseRepoController def __before__(self): super(ReposController, self).__before__() - def __load_defaults(self): + def _load_repo(self, repo_name): + repo_obj = Repository.get_by_repo_name(repo_name) + + if repo_obj is None: + h.not_mapped_error(repo_name) + return redirect(url('repos')) + + return repo_obj + + def __load_defaults(self, repo=None): acl_groups = RepoGroupList(RepoGroup.query().all(), perm_set=['group.write', 'group.admin']) c.repo_groups = RepoGroup.groups_choices(groups=acl_groups) c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) - repo_model = RepoModel() - c.users_array = repo_model.get_users_js() - c.users_groups_array = repo_model.get_users_groups_js() + # in case someone no longer have a group.write access to a repository + # pre fill the list with this entry, we don't care if this is the same + # but it will allow saving repo data properly. + + repo_group = None + if repo: + repo_group = repo.group + if repo_group and unicode(repo_group.group_id) not in c.repo_groups_choices: + c.repo_groups_choices.append(unicode(repo_group.group_id)) + c.repo_groups.append(RepoGroup._generate_choice(repo_group)) + choices, c.landing_revs = ScmModel().get_repo_landing_revs() c.landing_revs_choices = choices @@ -85,62 +102,24 @@ class ReposController(BaseRepoController :param repo_name: """ - self.__load_defaults() - - c.repo_info = db_repo = Repository.get_by_repo_name(repo_name) - repo = db_repo.scm_instance - - if c.repo_info is None: - h.not_mapped_error(repo_name) - return redirect(url('repos')) + c.repo_info = self._load_repo(repo_name) + self.__load_defaults(c.repo_info) ##override defaults for exact repo info here git/hg etc choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info) c.landing_revs_choices = choices - - c.default_user_id = User.get_default_user().user_id - c.in_public_journal = UserFollowing.query()\ - .filter(UserFollowing.user_id == c.default_user_id)\ - .filter(UserFollowing.follows_repository == c.repo_info).scalar() - - if c.repo_info.stats: - # this is on what revision we ended up so we add +1 for count - last_rev = c.repo_info.stats.stat_on_revision + 1 - else: - last_rev = 0 - c.stats_revision = last_rev - - c.repo_last_rev = repo.count() if repo.revisions else 0 - - if last_rev == 0 or c.repo_last_rev == 0: - c.stats_percentage = 0 - else: - c.stats_percentage = '%.2f' % ((float((last_rev)) / - c.repo_last_rev) * 100) - - c.repo_fields = RepositoryField.query()\ - .filter(RepositoryField.repository == db_repo).all() - defaults = RepoModel()._get_defaults(repo_name) - _repos = Repository.query().order_by(Repository.repo_name).all() - read_access_repos = RepoList(_repos) - c.repos_list = [('', _('--REMOVE FORK--'))] - c.repos_list += [(x.repo_id, x.repo_name) - for x in read_access_repos - if x.repo_id != c.repo_info.repo_id] - - defaults['id_fork_of'] = db_repo.fork.repo_id if db_repo.fork else '' return defaults def index(self, format='html'): """GET /repos: All items in the collection""" # url('repos') - repo_list = Repository.query()\ - .order_by(func.lower(Repository.repo_name))\ - .all() + _list = Repository.query()\ + .order_by(func.lower(Repository.repo_name))\ + .all() - c.repos_list = RepoList(repo_list, perm_set=['repository.admin']) + c.repos_list = RepoList(_list, perm_set=['repository.admin']) repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list, admin=True, super_user_actions=True) @@ -157,33 +136,19 @@ class ReposController(BaseRepoController self.__load_defaults() form_result = {} + task_id = None try: + # CanWriteToGroup validators checks permissions of this POST form_result = RepoForm(repo_groups=c.repo_groups_choices, landing_revs=c.landing_revs_choices)()\ .to_python(dict(request.POST)) - new_repo = RepoModel().create(form_result, - self.rhodecode_user.user_id) - if form_result['clone_uri']: - h.flash(_('Created repository %s from %s') \ - % (form_result['repo_name'], form_result['clone_uri']), - category='success') - else: - repo_url = h.link_to(form_result['repo_name'], - h.url('summary_home', repo_name=form_result['repo_name_full'])) - h.flash(h.literal(_('Created repository %s') % repo_url), - category='success') - - if request.POST.get('user_created'): - # created by regular non admin user - action_logger(self.rhodecode_user, 'user_created_repo', - form_result['repo_name_full'], self.ip_addr, - self.sa) - else: - action_logger(self.rhodecode_user, 'admin_created_repo', - form_result['repo_name_full'], self.ip_addr, - self.sa) - Session().commit() + # create is done sometimes async on celery, db transaction + # management is handled there. + task = RepoModel().create(form_result, self.authuser.user_id) + from celery.result import BaseAsyncResult + if isinstance(task, BaseAsyncResult): + task_id = task.task_id except formencode.Invalid, errors: return htmlfill.render( render('admin/repos/repo_add.html'), @@ -194,14 +159,14 @@ class ReposController(BaseRepoController except Exception: log.error(traceback.format_exc()) - msg = _('Error creating repository %s') \ - % form_result.get('repo_name') + msg = (_('Error creating repository %s') + % form_result.get('repo_name')) h.flash(msg, category='error') - if c.rhodecode_user.is_admin: - return redirect(url('repos')) return redirect(url('home')) - #redirect to our new repo ! - return redirect(url('summary_home', repo_name=new_repo.repo_name)) + + return redirect(h.url('repo_creating_home', + repo_name=form_result['repo_name_full'], + task_id=task_id)) @NotAnonymous() def create_repository(self): @@ -213,7 +178,11 @@ class ReposController(BaseRepoController #but maybe you have at least write permission to a parent group ? _gr = RepoGroup.get(parent_group) gr_name = _gr.group_name if _gr else None - if not HasReposGroupPermissionAny('group.admin', 'group.write')(group_name=gr_name): + # create repositories with write permission on group is set to true + create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')() + group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name) + group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name) + if not (group_admin or (group_write and create_on_write)): raise HTTPForbidden acl_groups = RepoGroupList(RepoGroup.query().all(), @@ -225,7 +194,7 @@ class ReposController(BaseRepoController c.new_repo = repo_name_slug(new_repo) ## apply the defaults from defaults page - defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True) + defaults = Setting.get_default_repo_settings(strip_prefix=True) if parent_group: defaults.update({'repo_group': parent_group}) @@ -237,6 +206,51 @@ class ReposController(BaseRepoController encoding="UTF-8" ) + @LoginRequired() + @NotAnonymous() + def repo_creating(self, repo_name): + c.repo = repo_name + c.task_id = request.GET.get('task_id') + if not c.repo: + raise HTTPNotFound() + return render('admin/repos/repo_creating.html') + + @LoginRequired() + @NotAnonymous() + @jsonify + def repo_check(self, repo_name): + c.repo = repo_name + task_id = request.GET.get('task_id') + + if task_id and task_id not in ['None']: + from kallithea import CELERY_ON + from celery.result import AsyncResult + if CELERY_ON: + task = AsyncResult(task_id) + if task.failed(): + raise HTTPInternalServerError(task.traceback) + + repo = Repository.get_by_repo_name(repo_name) + if repo and repo.repo_state == Repository.STATE_CREATED: + if repo.clone_uri: + clone_uri = repo.clone_uri_hidden + h.flash(_('Created repository %s from %s') + % (repo.repo_name, clone_uri), category='success') + else: + repo_url = h.link_to(repo.repo_name, + h.url('summary_home', + repo_name=repo.repo_name)) + fork = repo.fork + if fork: + fork_name = fork.repo_name + h.flash(h.literal(_('Forked repository %s as %s') + % (fork_name, repo_url)), category='success') + else: + h.flash(h.literal(_('Created repository %s') % repo_url), + category='success') + return {'result': True} + return {'result': False} + @HasRepoPermissionAllDecorator('repository.admin') def update(self, repo_name): """ @@ -247,7 +261,12 @@ class ReposController(BaseRepoController # h.form(url('repo', repo_name=ID), # method='put') # url('repo', repo_name=ID) - self.__load_defaults() + c.repo_info = self._load_repo(repo_name) + c.active = 'settings' + c.repo_fields = RepositoryField.query()\ + .filter(RepositoryField.repository == c.repo_info).all() + self.__load_defaults(c.repo_info) + repo_model = RepoModel() changed_name = repo_name #override the choices with extracted revisions ! @@ -270,7 +289,7 @@ class ReposController(BaseRepoController h.flash(_('Repository %s updated successfully') % repo_name, category='success') changed_name = repo.repo_name - action_logger(self.rhodecode_user, 'admin_updated_repo', + action_logger(self.authuser, 'admin_updated_repo', changed_name, self.ip_addr, self.sa) Session().commit() except formencode.Invalid, errors: @@ -317,7 +336,7 @@ class ReposController(BaseRepoController handle_forks = 'delete' h.flash(_('Deleted %s forks') % _forks, category='success') repo_model.delete(repo, forks=handle_forks) - action_logger(self.rhodecode_user, 'admin_deleted_repo', + action_logger(self.authuser, 'admin_deleted_repo', repo_name, self.ip_addr, self.sa) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Deleted repository %s') % repo_name, category='success') @@ -333,25 +352,57 @@ class ReposController(BaseRepoController return redirect(url('repos')) + @HasPermissionAllDecorator('hg.admin') + def show(self, repo_name, format='html'): + """GET /repos/repo_name: Show a specific item""" + # url('repo', repo_name=ID) + @HasRepoPermissionAllDecorator('repository.admin') - def set_repo_perm_member(self, repo_name): + def edit(self, repo_name): + """GET /repo_name/settings: Form to edit an existing item""" + # url('edit_repo', repo_name=ID) + defaults = self.__load_data(repo_name) + if 'clone_uri' in defaults: + del defaults['clone_uri'] + + c.repo_fields = RepositoryField.query()\ + .filter(RepositoryField.repository == c.repo_info).all() + c.active = 'settings' + return htmlfill.render( + render('admin/repos/repo_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + @HasRepoPermissionAllDecorator('repository.admin') + def edit_permissions(self, repo_name): + """GET /repo_name/settings: Form to edit an existing item""" + # url('edit_repo', repo_name=ID) + c.repo_info = self._load_repo(repo_name) + repo_model = RepoModel() + c.users_array = repo_model.get_users_js() + c.user_groups_array = repo_model.get_user_groups_js() + c.active = 'permissions' + defaults = RepoModel()._get_defaults(repo_name) + + return htmlfill.render( + render('admin/repos/repo_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + def edit_permissions_update(self, repo_name): form = RepoPermsForm()().to_python(request.POST) RepoModel()._update_permissions(repo_name, form['perms_new'], form['perms_updates']) #TODO: implement this - #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions', + #action_logger(self.authuser, 'admin_changed_repo_permissions', # repo_name, self.ip_addr, self.sa) Session().commit() h.flash(_('Repository permissions updated'), category='success') - return redirect(url('edit_repo', repo_name=repo_name)) + return redirect(url('edit_repo_perms', repo_name=repo_name)) - @HasRepoPermissionAllDecorator('repository.admin') - def delete_repo_perm_member(self, repo_name): - """ - DELETE an existing repository permission user - - :param repo_name: - """ + def edit_permissions_revoke(self, repo_name): try: obj_type = request.POST.get('obj_type') obj_id = None @@ -363,11 +414,11 @@ class ReposController(BaseRepoController if obj_type == 'user': RepoModel().revoke_user_permission(repo=repo_name, user=obj_id) elif obj_type == 'user_group': - RepoModel().revoke_users_group_permission( + RepoModel().revoke_user_group_permission( repo=repo_name, group_name=obj_id ) #TODO: implement this - #action_logger(self.rhodecode_user, 'admin_revoked_repo_permissions', + #action_logger(self.authuser, 'admin_revoked_repo_permissions', # repo_name, self.ip_addr, self.sa) Session().commit() except Exception: @@ -377,88 +428,83 @@ class ReposController(BaseRepoController raise HTTPInternalServerError() @HasRepoPermissionAllDecorator('repository.admin') - def repo_stats(self, repo_name): - """ - DELETE an existing repository statistics - - :param repo_name: - """ + def edit_fields(self, repo_name): + """GET /repo_name/settings: Form to edit an existing item""" + # url('edit_repo', repo_name=ID) + c.repo_info = self._load_repo(repo_name) + c.repo_fields = RepositoryField.query()\ + .filter(RepositoryField.repository == c.repo_info).all() + c.active = 'fields' + if request.POST: - try: - RepoModel().delete_stats(repo_name) - Session().commit() - except Exception, e: - log.error(traceback.format_exc()) - h.flash(_('An error occurred during deletion of repository stats'), - category='error') - return redirect(url('edit_repo', repo_name=repo_name)) + return redirect(url('repo_edit_fields')) + return render('admin/repos/repo_edit.html') @HasRepoPermissionAllDecorator('repository.admin') - def repo_cache(self, repo_name): - """ - INVALIDATE existing repository cache - - :param repo_name: - """ - + def create_repo_field(self, repo_name): try: - ScmModel().mark_for_invalidation(repo_name) + form_result = RepoFieldForm()().to_python(dict(request.POST)) + new_field = RepositoryField() + new_field.repository = Repository.get_by_repo_name(repo_name) + new_field.field_key = form_result['new_field_key'] + new_field.field_type = form_result['new_field_type'] # python type + new_field.field_value = form_result['new_field_value'] # set initial blank value + new_field.field_desc = form_result['new_field_desc'] + new_field.field_label = form_result['new_field_label'] + Session().add(new_field) Session().commit() except Exception, e: log.error(traceback.format_exc()) - h.flash(_('An error occurred during cache invalidation'), - category='error') - return redirect(url('edit_repo', repo_name=repo_name)) + msg = _('An error occurred during creation of field') + if isinstance(e, formencode.Invalid): + msg += ". " + e.msg + h.flash(msg, category='error') + return redirect(url('edit_repo_fields', repo_name=repo_name)) @HasRepoPermissionAllDecorator('repository.admin') - def repo_locking(self, repo_name): - """ - Unlock repository when it is locked ! - - :param repo_name: - """ - + def delete_repo_field(self, repo_name, field_id): + field = RepositoryField.get_or_404(field_id) try: - repo = Repository.get_by_repo_name(repo_name) - if request.POST.get('set_lock'): - Repository.lock(repo, c.rhodecode_user.user_id) - elif request.POST.get('set_unlock'): - Repository.unlock(repo) + Session().delete(field) + Session().commit() except Exception, e: log.error(traceback.format_exc()) - h.flash(_('An error occurred during unlocking'), - category='error') - return redirect(url('edit_repo', repo_name=repo_name)) - - @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') - def toggle_locking(self, repo_name): - """ - Toggle locking of repository by simple GET call to url - - :param repo_name: - """ - - try: - repo = Repository.get_by_repo_name(repo_name) - - if repo.enable_locking: - if repo.locked[0]: - Repository.unlock(repo) - action = _('Unlocked') - else: - Repository.lock(repo, c.rhodecode_user.user_id) - action = _('Locked') - - h.flash(_('Repository has been %s') % action, - category='success') - except Exception, e: - log.error(traceback.format_exc()) - h.flash(_('An error occurred during unlocking'), - category='error') - return redirect(url('summary_home', repo_name=repo_name)) + msg = _('An error occurred during removal of field') + h.flash(msg, category='error') + return redirect(url('edit_repo_fields', repo_name=repo_name)) @HasRepoPermissionAllDecorator('repository.admin') - def repo_public_journal(self, repo_name): + def edit_advanced(self, repo_name): + """GET /repo_name/settings: Form to edit an existing item""" + # url('edit_repo', repo_name=ID) + c.repo_info = self._load_repo(repo_name) + c.default_user_id = User.get_default_user().user_id + c.in_public_journal = UserFollowing.query()\ + .filter(UserFollowing.user_id == c.default_user_id)\ + .filter(UserFollowing.follows_repository == c.repo_info).scalar() + + _repos = Repository.query().order_by(Repository.repo_name).all() + read_access_repos = RepoList(_repos) + c.repos_list = [(None, _('-- Not a fork --'))] + c.repos_list += [(x.repo_id, x.repo_name) + for x in read_access_repos + if x.repo_id != c.repo_info.repo_id] + + defaults = { + 'id_fork_of': c.repo_info.fork.repo_id if c.repo_info.fork else '' + } + + c.active = 'advanced' + if request.POST: + return redirect(url('repo_edit_advanced')) + return htmlfill.render( + render('admin/repos/repo_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + @HasRepoPermissionAllDecorator('repository.admin') + def edit_advanced_journal(self, repo_name): """ Set's this repository to be visible in public journal, in other words assing default user to follow this repo @@ -483,28 +529,11 @@ class ReposController(BaseRepoController else: h.flash(_('Token mismatch'), category='error') - return redirect(url('edit_repo', repo_name=repo_name)) + return redirect(url('edit_repo_advanced', repo_name=repo_name)) + @HasRepoPermissionAllDecorator('repository.admin') - def repo_pull(self, repo_name): - """ - Runs task to update given repository with remote changes, - ie. make pull on remote location - - :param repo_name: - """ - try: - ScmModel().pull_changes(repo_name, self.rhodecode_user.username) - h.flash(_('Pulled from remote location'), category='success') - except Exception, e: - log.error(traceback.format_exc()) - h.flash(_('An error occurred during pull from remote location'), - category='error') - - return redirect(url('edit_repo', repo_name=repo_name)) - - @HasRepoPermissionAllDecorator('repository.admin') - def repo_as_fork(self, repo_name): + def edit_advanced_fork(self, repo_name): """ Mark given repository as a fork of another @@ -513,66 +542,136 @@ class ReposController(BaseRepoController try: fork_id = request.POST.get('id_fork_of') repo = ScmModel().mark_as_fork(repo_name, fork_id, - self.rhodecode_user.username) + self.authuser.username) fork = repo.fork.repo_name if repo.fork else _('Nothing') Session().commit() h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork), category='success') + except RepositoryError, e: + log.error(traceback.format_exc()) + h.flash(str(e), category='error') except Exception, e: log.error(traceback.format_exc()) h.flash(_('An error occurred during this operation'), category='error') - return redirect(url('edit_repo', repo_name=repo_name)) + return redirect(url('edit_repo_advanced', repo_name=repo_name)) + + @HasRepoPermissionAllDecorator('repository.admin') + def edit_advanced_locking(self, repo_name): + """ + Unlock repository when it is locked ! + + :param repo_name: + """ + try: + repo = Repository.get_by_repo_name(repo_name) + if request.POST.get('set_lock'): + Repository.lock(repo, c.authuser.user_id) + h.flash(_('Locked repository'), category='success') + elif request.POST.get('set_unlock'): + Repository.unlock(repo) + h.flash(_('Unlocked repository'), category='success') + except Exception, e: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during unlocking'), + category='error') + return redirect(url('edit_repo_advanced', repo_name=repo_name)) - @HasPermissionAllDecorator('hg.admin') - def show(self, repo_name, format='html'): - """GET /repos/repo_name: Show a specific item""" - # url('repo', repo_name=ID) + @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') + def toggle_locking(self, repo_name): + """ + Toggle locking of repository by simple GET call to url + + :param repo_name: + """ + + try: + repo = Repository.get_by_repo_name(repo_name) + + if repo.enable_locking: + if repo.locked[0]: + Repository.unlock(repo) + action = _('Unlocked') + else: + Repository.lock(repo, c.authuser.user_id) + action = _('Locked') + + h.flash(_('Repository has been %s') % action, + category='success') + except Exception, e: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during unlocking'), + category='error') + return redirect(url('summary_home', repo_name=repo_name)) @HasRepoPermissionAllDecorator('repository.admin') - def edit(self, repo_name, format='html'): - """GET /repos/repo_name/edit: Form to edit an existing item""" + def edit_caches(self, repo_name): + """GET /repo_name/settings: Form to edit an existing item""" # url('edit_repo', repo_name=ID) - defaults = self.__load_data(repo_name) + c.repo_info = self._load_repo(repo_name) + c.active = 'caches' + if request.POST: + try: + ScmModel().mark_for_invalidation(repo_name, delete=True) + Session().commit() + h.flash(_('Cache invalidation successful'), + category='success') + except Exception, e: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during cache invalidation'), + category='error') - return htmlfill.render( - render('admin/repos/repo_edit.html'), - defaults=defaults, - encoding="UTF-8", - force_defaults=False - ) + return redirect(url('edit_repo_caches', repo_name=c.repo_name)) + return render('admin/repos/repo_edit.html') - @HasPermissionAllDecorator('hg.admin') - def create_repo_field(self, repo_name): - try: - form_result = RepoFieldForm()().to_python(dict(request.POST)) - new_field = RepositoryField() - new_field.repository = Repository.get_by_repo_name(repo_name) - new_field.field_key = form_result['new_field_key'] - new_field.field_type = form_result['new_field_type'] # python type - new_field.field_value = form_result['new_field_value'] # set initial blank value - new_field.field_desc = form_result['new_field_desc'] - new_field.field_label = form_result['new_field_label'] - Session().add(new_field) - Session().commit() + @HasRepoPermissionAllDecorator('repository.admin') + def edit_remote(self, repo_name): + """GET /repo_name/settings: Form to edit an existing item""" + # url('edit_repo', repo_name=ID) + c.repo_info = self._load_repo(repo_name) + c.active = 'remote' + if request.POST: + try: + ScmModel().pull_changes(repo_name, self.authuser.username) + h.flash(_('Pulled from remote location'), category='success') + except Exception, e: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during pull from remote location'), + category='error') + return redirect(url('edit_repo_remote', repo_name=c.repo_name)) + return render('admin/repos/repo_edit.html') + + @HasRepoPermissionAllDecorator('repository.admin') + def edit_statistics(self, repo_name): + """GET /repo_name/settings: Form to edit an existing item""" + # url('edit_repo', repo_name=ID) + c.repo_info = self._load_repo(repo_name) + repo = c.repo_info.scm_instance - except Exception, e: - log.error(traceback.format_exc()) - msg = _('An error occurred during creation of field') - if isinstance(e, formencode.Invalid): - msg += ". " + e.msg - h.flash(msg, category='error') - return redirect(url('edit_repo', repo_name=repo_name)) + if c.repo_info.stats: + # this is on what revision we ended up so we add +1 for count + last_rev = c.repo_info.stats.stat_on_revision + 1 + else: + last_rev = 0 + c.stats_revision = last_rev + + c.repo_last_rev = repo.count() if repo.revisions else 0 - @HasPermissionAllDecorator('hg.admin') - def delete_repo_field(self, repo_name, field_id): - field = RepositoryField.get_or_404(field_id) - try: - Session().delete(field) - Session().commit() - except Exception, e: - log.error(traceback.format_exc()) - msg = _('An error occurred during removal of field') - h.flash(msg, category='error') - return redirect(url('edit_repo', repo_name=repo_name)) + if last_rev == 0 or c.repo_last_rev == 0: + c.stats_percentage = 0 + else: + c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100) + + c.active = 'statistics' + if request.POST: + try: + RepoModel().delete_stats(repo_name) + Session().commit() + except Exception, e: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during deletion of repository stats'), + category='error') + return redirect(url('edit_repo_statistics', repo_name=c.repo_name)) + + return render('admin/repos/repo_edit.html') diff --git a/rhodecode/controllers/admin/settings.py b/kallithea/controllers/admin/settings.py rename from rhodecode/controllers/admin/settings.py rename to kallithea/controllers/admin/settings.py --- a/rhodecode/controllers/admin/settings.py +++ b/kallithea/controllers/admin/settings.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.admin.settings - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - settings controller for rhodecode admin - - :created_on: Jul 14, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,40 +11,44 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.admin.settings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +settings controller for Kallithea admin + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jul 14, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import time import logging import traceback import formencode -import pkg_resources -import platform -from sqlalchemy import func from formencode import htmlfill -from pylons import request, session, tmpl_context as c, url, config -from pylons.controllers.util import abort, redirect +from pylons import request, tmpl_context as c, url, config +from pylons.controllers.util import redirect from pylons.i18n.translation import _ -from rhodecode.lib import helpers as h -from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \ - HasPermissionAnyDecorator, NotAnonymous, HasPermissionAny,\ - HasReposGroupPermissionAll, HasReposGroupPermissionAny, AuthUser -from rhodecode.lib.base import BaseController, render -from rhodecode.lib.celerylib import tasks, run_task -from rhodecode.lib.exceptions import HgsubversionImportError -from rhodecode.lib.utils import repo2db_mapper, set_rhodecode_config, \ - check_git_version -from rhodecode.model.db import RhodeCodeUi, Repository, RepoGroup, \ - RhodeCodeSetting, PullRequest, PullRequestReviewers -from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \ +from kallithea.lib import helpers as h +from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator +from kallithea.lib.base import BaseController, render +from kallithea.lib.celerylib import tasks, run_task +from kallithea.lib.exceptions import HgsubversionImportError +from kallithea.lib.utils import repo2db_mapper, set_app_settings +from kallithea.model.db import Ui, Repository, Setting +from kallithea.model.forms import ApplicationSettingsForm, \ ApplicationUiSettingsForm, ApplicationVisualisationForm -from rhodecode.model.scm import ScmModel, RepoGroupList -from rhodecode.model.user import UserModel -from rhodecode.model.repo import RepoModel -from rhodecode.model.db import User -from rhodecode.model.notification import EmailNotificationModel -from rhodecode.model.meta import Session -from rhodecode.lib.utils2 import str2bool, safe_unicode -from rhodecode.lib.compat import json +from kallithea.model.scm import ScmModel +from kallithea.model.notification import EmailNotificationModel +from kallithea.model.meta import Session +from kallithea.lib.utils2 import str2bool, safe_unicode, safe_str +from kallithea.lib.compat import json log = logging.getLogger(__name__) @@ -69,168 +62,37 @@ class SettingsController(BaseController) @LoginRequired() def __before__(self): super(SettingsController, self).__before__() - c.modules = sorted([(p.project_name, p.version) - for p in pkg_resources.working_set] - + [('git', check_git_version())], - key=lambda k: k[0].lower()) - c.py_version = platform.python_version() - c.platform = platform.platform() - @HasPermissionAllDecorator('hg.admin') - def index(self, format='html'): - """GET /admin/settings: All items in the collection""" - # url('admin_settings') - - defaults = RhodeCodeSetting.get_app_settings() - defaults.update(self._get_hg_ui_settings()) + def _get_hg_ui_settings(self): + ret = Ui.query().all() - return htmlfill.render( - render('admin/settings/settings.html'), - defaults=defaults, - encoding="UTF-8", - force_defaults=False - ) + if not ret: + raise Exception('Could not get application ui settings !') + settings = {} + for each in ret: + k = each.ui_key + v = each.ui_value + if k == '/': + k = 'root_path' - @HasPermissionAllDecorator('hg.admin') - def create(self): - """POST /admin/settings: Create a new item""" - # url('admin_settings') + if k == 'push_ssl': + v = str2bool(v) + + if k.find('.') != -1: + k = k.replace('.', '_') - @HasPermissionAllDecorator('hg.admin') - def new(self, format='html'): - """GET /admin/settings/new: Form to create a new item""" - # url('admin_new_setting') + if each.ui_section in ['hooks', 'extensions']: + v = each.ui_active + + settings[each.ui_section + '_' + k] = v + return settings @HasPermissionAllDecorator('hg.admin') - def update(self, setting_id): - """PUT /admin/settings/setting_id: Update an existing item""" - # Forms posted to this method should contain a hidden field: - # - # Or using helpers: - # h.form(url('admin_setting', setting_id=ID), - # method='put') - # url('admin_setting', setting_id=ID) - - if setting_id == 'mapping': - rm_obsolete = request.POST.get('destroy', False) - invalidate_cache = request.POST.get('invalidate', False) - log.debug('rescanning repo location with destroy obsolete=%s' - % (rm_obsolete,)) - - if invalidate_cache: - log.debug('invalidating all repositories cache') - for repo in Repository.get_all(): - ScmModel().mark_for_invalidation(repo.repo_name) - - filesystem_repos = ScmModel().repo_scan() - added, removed = repo2db_mapper(filesystem_repos, rm_obsolete) - _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-' - h.flash(_('Repositories successfully ' - 'rescanned added: %s ; removed: %s') % - (_repr(added), _repr(removed)), - category='success') - - if setting_id == 'whoosh': - repo_location = self._get_hg_ui_settings()['paths_root_path'] - full_index = request.POST.get('full_index', False) - run_task(tasks.whoosh_index, repo_location, full_index) - h.flash(_('Whoosh reindex task scheduled'), category='success') - - if setting_id == 'global': - - application_form = ApplicationSettingsForm()() - try: - form_result = application_form.to_python(dict(request.POST)) - except formencode.Invalid, errors: - return htmlfill.render( - render('admin/settings/settings.html'), - defaults=errors.value, - errors=errors.error_dict or {}, - prefix_error=False, - encoding="UTF-8" - ) - - try: - sett1 = RhodeCodeSetting.get_by_name_or_create('title') - sett1.app_settings_value = form_result['rhodecode_title'] - Session().add(sett1) - - sett2 = RhodeCodeSetting.get_by_name_or_create('realm') - sett2.app_settings_value = form_result['rhodecode_realm'] - Session().add(sett2) - - sett3 = RhodeCodeSetting.get_by_name_or_create('ga_code') - sett3.app_settings_value = form_result['rhodecode_ga_code'] - Session().add(sett3) - - Session().commit() - set_rhodecode_config(config) - h.flash(_('Updated application settings'), category='success') - - except Exception: - log.error(traceback.format_exc()) - h.flash(_('Error occurred during updating ' - 'application settings'), - category='error') - - if setting_id == 'visual': - - application_form = ApplicationVisualisationForm()() - try: - form_result = application_form.to_python(dict(request.POST)) - except formencode.Invalid, errors: - return htmlfill.render( - render('admin/settings/settings.html'), - defaults=errors.value, - errors=errors.error_dict or {}, - prefix_error=False, - encoding="UTF-8" - ) - - try: - #TODO: rewrite this to something less ugly - sett1 = RhodeCodeSetting.get_by_name_or_create('show_public_icon') - sett1.app_settings_value = \ - form_result['rhodecode_show_public_icon'] - Session().add(sett1) - - sett2 = RhodeCodeSetting.get_by_name_or_create('show_private_icon') - sett2.app_settings_value = \ - form_result['rhodecode_show_private_icon'] - Session().add(sett2) - - sett3 = RhodeCodeSetting.get_by_name_or_create('stylify_metatags') - sett3.app_settings_value = \ - form_result['rhodecode_stylify_metatags'] - Session().add(sett3) - - sett4 = RhodeCodeSetting.get_by_name_or_create('repository_fields') - sett4.app_settings_value = \ - form_result['rhodecode_repository_fields'] - Session().add(sett4) - - sett5 = RhodeCodeSetting.get_by_name_or_create('dashboard_items') - sett5.app_settings_value = \ - form_result['rhodecode_dashboard_items'] - Session().add(sett5) - - sett6 = RhodeCodeSetting.get_by_name_or_create('show_version') - sett6.app_settings_value = \ - form_result['rhodecode_show_version'] - Session().add(sett6) - - Session().commit() - set_rhodecode_config(config) - h.flash(_('Updated visualisation settings'), - category='success') - - except Exception: - log.error(traceback.format_exc()) - h.flash(_('Error occurred during updating ' - 'visualisation settings'), - category='error') - - if setting_id == 'vcs': + def settings_vcs(self): + """GET /admin/settings: All items in the collection""" + # url('admin_settings') + c.active = 'vcs' + if request.POST: application_form = ApplicationUiSettingsForm()() try: form_result = application_form.to_python(dict(request.POST)) @@ -244,61 +106,61 @@ class SettingsController(BaseController) ) try: - sett = RhodeCodeUi.get_by_key('push_ssl') + sett = Ui.get_by_key('push_ssl') sett.ui_value = form_result['web_push_ssl'] Session().add(sett) if c.visual.allow_repo_location_change: - sett = RhodeCodeUi.get_by_key('/') + sett = Ui.get_by_key('/') sett.ui_value = form_result['paths_root_path'] Session().add(sett) #HOOKS - sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_UPDATE) + sett = Ui.get_by_key(Ui.HOOK_UPDATE) sett.ui_active = form_result['hooks_changegroup_update'] Session().add(sett) - sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_REPO_SIZE) + sett = Ui.get_by_key(Ui.HOOK_REPO_SIZE) sett.ui_active = form_result['hooks_changegroup_repo_size'] Session().add(sett) - sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_PUSH) + sett = Ui.get_by_key(Ui.HOOK_PUSH) sett.ui_active = form_result['hooks_changegroup_push_logger'] Session().add(sett) - sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_PULL) + sett = Ui.get_by_key(Ui.HOOK_PULL) sett.ui_active = form_result['hooks_outgoing_pull_logger'] Session().add(sett) ## EXTENSIONS - sett = RhodeCodeUi.get_by_key('largefiles') + sett = Ui.get_by_key('largefiles') if not sett: #make one if it's not there ! - sett = RhodeCodeUi() + sett = Ui() sett.ui_key = 'largefiles' sett.ui_section = 'extensions' sett.ui_active = form_result['extensions_largefiles'] Session().add(sett) - sett = RhodeCodeUi.get_by_key('hgsubversion') + sett = Ui.get_by_key('hgsubversion') if not sett: #make one if it's not there ! - sett = RhodeCodeUi() + sett = Ui() sett.ui_key = 'hgsubversion' sett.ui_section = 'extensions' sett.ui_active = form_result['extensions_hgsubversion'] if sett.ui_active: try: - import hgsubversion + import hgsubversion # pragma: no cover except ImportError: raise HgsubversionImportError Session().add(sett) -# sett = RhodeCodeUi.get_by_key('hggit') +# sett = Ui.get_by_key('hggit') # if not sett: # #make one if it's not there ! -# sett = RhodeCodeUi() +# sett = Ui() # sett.ui_key = 'hggit' # sett.ui_section = 'extensions' # @@ -320,39 +182,181 @@ class SettingsController(BaseController) h.flash(_('Error occurred during updating ' 'application settings'), category='error') - if setting_id == 'hooks': - if c.visual.allow_custom_hooks_settings: - ui_key = request.POST.get('new_hook_ui_key') - ui_value = request.POST.get('new_hook_ui_value') - try: + defaults = Setting.get_app_settings() + defaults.update(self._get_hg_ui_settings()) + + return htmlfill.render( + render('admin/settings/settings.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + @HasPermissionAllDecorator('hg.admin') + def settings_mapping(self): + """GET /admin/settings/mapping: All items in the collection""" + # url('admin_settings_mapping') + c.active = 'mapping' + if request.POST: + rm_obsolete = request.POST.get('destroy', False) + install_git_hooks = request.POST.get('hooks', False) + invalidate_cache = request.POST.get('invalidate', False) + log.debug('rescanning repo location with destroy obsolete=%s and ' + 'install git hooks=%s' % (rm_obsolete,install_git_hooks)) + + if invalidate_cache: + log.debug('invalidating all repositories cache') + for repo in Repository.get_all(): + ScmModel().mark_for_invalidation(repo.repo_name, delete=True) + + filesystem_repos = ScmModel().repo_scan() + added, removed = repo2db_mapper(filesystem_repos, rm_obsolete, + install_git_hook=install_git_hooks) + _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-' + h.flash(_('Repositories successfully ' + 'rescanned added: %s ; removed: %s') % + (_repr(added), _repr(removed)), + category='success') + return redirect(url('admin_settings_mapping')) + + defaults = Setting.get_app_settings() + defaults.update(self._get_hg_ui_settings()) - if ui_value and ui_key: - RhodeCodeUi.create_or_update_hook(ui_key, ui_value) - h.flash(_('Added new hook'), - category='success') + return htmlfill.render( + render('admin/settings/settings.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + @HasPermissionAllDecorator('hg.admin') + def settings_global(self): + """GET /admin/settings/global: All items in the collection""" + # url('admin_settings_global') + c.active = 'global' + if request.POST: + application_form = ApplicationSettingsForm()() + try: + form_result = application_form.to_python(dict(request.POST)) + except formencode.Invalid, errors: + return htmlfill.render( + render('admin/settings/settings.html'), + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8") + + try: + sett1 = Setting.create_or_update('title', + form_result['title']) + Session().add(sett1) + + sett2 = Setting.create_or_update('realm', + form_result['realm']) + Session().add(sett2) + + sett3 = Setting.create_or_update('ga_code', + form_result['ga_code']) + Session().add(sett3) + + sett4 = Setting.create_or_update('captcha_public_key', + form_result['captcha_public_key']) + Session().add(sett4) + + sett5 = Setting.create_or_update('captcha_private_key', + form_result['captcha_private_key']) + Session().add(sett5) + + Session().commit() + set_app_settings(config) + h.flash(_('Updated application settings'), category='success') - # check for edits - update = False - _d = request.POST.dict_of_lists() - for k, v in zip(_d.get('hook_ui_key', []), - _d.get('hook_ui_value_new', [])): - RhodeCodeUi.create_or_update_hook(k, v) - update = True + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during updating ' + 'application settings'), + category='error') + + return redirect(url('admin_settings_global')) + + defaults = Setting.get_app_settings() + defaults.update(self._get_hg_ui_settings()) + + return htmlfill.render( + render('admin/settings/settings.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + @HasPermissionAllDecorator('hg.admin') + def settings_visual(self): + """GET /admin/settings/visual: All items in the collection""" + # url('admin_settings_visual') + c.active = 'visual' + if request.POST: + application_form = ApplicationVisualisationForm()() + try: + form_result = application_form.to_python(dict(request.POST)) + except formencode.Invalid, errors: + return htmlfill.render( + render('admin/settings/settings.html'), + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8" + ) - if update: - h.flash(_('Updated hooks'), category='success') - Session().commit() - except Exception: - log.error(traceback.format_exc()) - h.flash(_('Error occurred during hook creation'), - category='error') + try: + settings = [ + ('show_public_icon', 'show_public_icon', 'bool'), + ('show_private_icon', 'show_private_icon', 'bool'), + ('stylify_metatags', 'stylify_metatags', 'bool'), + ('repository_fields', 'repository_fields', 'bool'), + ('dashboard_items', 'dashboard_items', 'int'), + ('admin_grid_items', 'admin_grid_items', 'int'), + ('show_version', 'show_version', 'bool'), + ('use_gravatar', 'use_gravatar', 'bool'), + ('gravatar_url', 'gravatar_url', 'unicode'), + ('clone_uri_tmpl', 'clone_uri_tmpl', 'unicode'), + ] + for setting, form_key, type_ in settings: + sett = Setting.create_or_update(setting, + form_result[form_key], type_) + Session().add(sett) + + Session().commit() + set_app_settings(config) + h.flash(_('Updated visualisation settings'), + category='success') - return redirect(url('admin_edit_setting', setting_id='hooks')) + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during updating ' + 'visualisation settings'), + category='error') + + return redirect(url('admin_settings_visual')) + + defaults = Setting.get_app_settings() + defaults.update(self._get_hg_ui_settings()) - if setting_id == 'email': + return htmlfill.render( + render('admin/settings/settings.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + @HasPermissionAllDecorator('hg.admin') + def settings_email(self): + """GET /admin/settings/email: All items in the collection""" + # url('admin_settings_email') + c.active = 'email' + if request.POST: test_email = request.POST.get('test_email') - test_email_subj = 'RhodeCode TestEmail' - test_email_body = 'RhodeCode Email test' + test_email_subj = 'Kallithea test email' + test_email_body = ('Kallithea Email test, ' + 'Kallithea version: %s' % c.kallithea_version) + if not test_email: + h.flash(_('Please enter email address'), category='error') + return redirect(url('admin_settings_email')) test_email_html_body = EmailNotificationModel()\ .get_email_tmpl(EmailNotificationModel.TYPE_DEFAULT, @@ -363,174 +367,155 @@ class SettingsController(BaseController) run_task(tasks.send_email, recipients, test_email_subj, test_email_body, test_email_html_body) - h.flash(_('Email task created'), category='success') - return redirect(url('admin_settings')) + h.flash(_('Send email task created'), category='success') + return redirect(url('admin_settings_email')) - @HasPermissionAllDecorator('hg.admin') - def delete(self, setting_id): - """DELETE /admin/settings/setting_id: Delete an existing item""" - # Forms posted to this method should contain a hidden field: - # - # Or using helpers: - # h.form(url('admin_setting', setting_id=ID), - # method='delete') - # url('admin_setting', setting_id=ID) - if setting_id == 'hooks': - hook_id = request.POST.get('hook_id') - RhodeCodeUi.delete(hook_id) - Session().commit() + defaults = Setting.get_app_settings() + defaults.update(self._get_hg_ui_settings()) - @HasPermissionAllDecorator('hg.admin') - def show(self, setting_id, format='html'): - """ - GET /admin/settings/setting_id: Show a specific item""" - # url('admin_setting', setting_id=ID) - - @HasPermissionAllDecorator('hg.admin') - def edit(self, setting_id, format='html'): - """ - GET /admin/settings/setting_id/edit: Form to - edit an existing item""" - # url('admin_edit_setting', setting_id=ID) - - c.hooks = RhodeCodeUi.get_builtin_hooks() - c.custom_hooks = RhodeCodeUi.get_custom_hooks() + import kallithea + c.ini = kallithea.CONFIG return htmlfill.render( - render('admin/settings/hooks.html'), - defaults={}, + render('admin/settings/settings.html'), + defaults=defaults, encoding="UTF-8", - force_defaults=False - ) + force_defaults=False) - def _load_my_repos_data(self): - repos_list = Session().query(Repository)\ - .filter(Repository.user_id == - self.rhodecode_user.user_id)\ - .order_by(func.lower(Repository.repo_name)).all() + @HasPermissionAllDecorator('hg.admin') + def settings_hooks(self): + """GET /admin/settings/hooks: All items in the collection""" + # url('admin_settings_hooks') + c.active = 'hooks' + if request.POST: + if c.visual.allow_custom_hooks_settings: + ui_key = request.POST.get('new_hook_ui_key') + ui_value = request.POST.get('new_hook_ui_value') - repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, - admin=True) - #json used to render the grid - return json.dumps(repos_data) + hook_id = request.POST.get('hook_id') + + try: + if ui_value and ui_key: + Ui.create_or_update_hook(ui_key, ui_value) + h.flash(_('Added new hook'), category='success') + elif hook_id: + Ui.delete(hook_id) + Session().commit() - @NotAnonymous() - def my_account(self): - """ - GET /_admin/my_account Displays info about my account - """ - # url('admin_settings_my_account') - - c.user = User.get(self.rhodecode_user.user_id) - c.perm_user = AuthUser(user_id=self.rhodecode_user.user_id, - ip_addr=self.ip_addr) - c.ldap_dn = c.user.ldap_dn + # check for edits + update = False + _d = request.POST.dict_of_lists() + for k, v in zip(_d.get('hook_ui_key', []), + _d.get('hook_ui_value_new', [])): + Ui.create_or_update_hook(k, v) + update = True - if c.user.username == 'default': - h.flash(_("You can't edit this user since it's" - " crucial for entire application"), category='warning') - return redirect(url('users')) + if update: + h.flash(_('Updated hooks'), category='success') + Session().commit() + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during hook creation'), + category='error') - #json used to render the grid - c.data = self._load_my_repos_data() + return redirect(url('admin_settings_hooks')) + + defaults = Setting.get_app_settings() + defaults.update(self._get_hg_ui_settings()) - defaults = c.user.get_dict() + c.hooks = Ui.get_builtin_hooks() + c.custom_hooks = Ui.get_custom_hooks() - c.form = htmlfill.render( - render('admin/users/user_edit_my_account_form.html'), + return htmlfill.render( + render('admin/settings/settings.html'), defaults=defaults, encoding="UTF-8", - force_defaults=False - ) - return render('admin/users/user_edit_my_account.html') + force_defaults=False) + + @HasPermissionAllDecorator('hg.admin') + def settings_search(self): + """GET /admin/settings/search: All items in the collection""" + # url('admin_settings_search') + c.active = 'search' + if request.POST: + repo_location = self._get_hg_ui_settings()['paths_root_path'] + full_index = request.POST.get('full_index', False) + run_task(tasks.whoosh_index, repo_location, full_index) + h.flash(_('Whoosh reindex task scheduled'), category='success') + return redirect(url('admin_settings_search')) + + defaults = Setting.get_app_settings() + defaults.update(self._get_hg_ui_settings()) - @NotAnonymous() - def my_account_update(self): - """PUT /_admin/my_account_update: Update an existing item""" - # Forms posted to this method should contain a hidden field: - # - # Or using helpers: - # h.form(url('admin_settings_my_account_update'), - # method='put') - # url('admin_settings_my_account_update', id=ID) - uid = self.rhodecode_user.user_id - c.user = User.get(self.rhodecode_user.user_id) - c.perm_user = AuthUser(user_id=self.rhodecode_user.user_id, - ip_addr=self.ip_addr) - c.ldap_dn = c.user.ldap_dn - email = self.rhodecode_user.email - _form = UserForm(edit=True, - old_data={'user_id': uid, 'email': email})() - form_result = {} - try: - form_result = _form.to_python(dict(request.POST)) - skip_attrs = ['admin', 'active'] # skip attr for my account - if c.ldap_dn: - #forbid updating username for ldap accounts - skip_attrs.append('username') - UserModel().update(uid, form_result, skip_attrs=skip_attrs) - h.flash(_('Your account was updated successfully'), - category='success') - Session().commit() - except formencode.Invalid, errors: - #json used to render the grid - c.data = self._load_my_repos_data() - c.form = htmlfill.render( - render('admin/users/user_edit_my_account_form.html'), - defaults=errors.value, - errors=errors.error_dict or {}, - prefix_error=False, - encoding="UTF-8") - return render('admin/users/user_edit_my_account.html') - except Exception: - log.error(traceback.format_exc()) - h.flash(_('Error occurred during update of user %s') \ - % form_result.get('username'), category='error') + return htmlfill.render( + render('admin/settings/settings.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + @HasPermissionAllDecorator('hg.admin') + def settings_system(self): + """GET /admin/settings/system: All items in the collection""" + # url('admin_settings_system') + c.active = 'system' + + defaults = Setting.get_app_settings() + defaults.update(self._get_hg_ui_settings()) + + import kallithea + c.ini = kallithea.CONFIG + c.update_url = defaults.get('update_url') + server_info = Setting.get_server_info() + for key, val in server_info.iteritems(): + setattr(c, key, val) + + return htmlfill.render( + render('admin/settings/settings.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) - return redirect(url('my_account')) - - @NotAnonymous() - def my_account_my_pullrequests(self): - c.show_closed = request.GET.get('pr_show_closed') - - def _filter(pr): - s = sorted(pr, key=lambda o: o.created_on, reverse=True) - if not c.show_closed: - s = filter(lambda p: p.status != PullRequest.STATUS_CLOSED, s) - return s + @HasPermissionAllDecorator('hg.admin') + def settings_system_update(self): + """GET /admin/settings/system/updates: All items in the collection""" + # url('admin_settings_system_update') + import json + import urllib2 + from kallithea.lib.verlib import NormalizedVersion + from kallithea import __version__ - c.my_pull_requests = _filter(PullRequest.query()\ - .filter(PullRequest.user_id == - self.rhodecode_user.user_id)\ - .all()) - - c.participate_in_pull_requests = _filter([ - x.pull_request for x in PullRequestReviewers.query()\ - .filter(PullRequestReviewers.user_id == - self.rhodecode_user.user_id).all()]) - - return render('admin/users/user_edit_my_account_pullrequests.html') + defaults = Setting.get_app_settings() + defaults.update(self._get_hg_ui_settings()) + _update_url = defaults.get('update_url', '') + _update_url = "" # FIXME: disabled - def _get_hg_ui_settings(self): - ret = RhodeCodeUi.query().all() - - if not ret: - raise Exception('Could not get application ui settings !') - settings = {} - for each in ret: - k = each.ui_key - v = each.ui_value - if k == '/': - k = 'root_path' + _err = lambda s: '
%s
' % (s) + try: + import kallithea + ver = kallithea.__version__ + log.debug('Checking for upgrade on `%s` server' % _update_url) + opener = urllib2.build_opener() + opener.addheaders = [('User-agent', 'Kallithea-SCM/%s' % ver)] + response = opener.open(_update_url) + response_data = response.read() + data = json.loads(response_data) + except urllib2.URLError, e: + log.error(traceback.format_exc()) + return _err('Failed to contact upgrade server: %r' % e) + except ValueError, e: + log.error(traceback.format_exc()) + return _err('Bad data sent from update server') - if k == 'push_ssl': - v = str2bool(v) - - if k.find('.') != -1: - k = k.replace('.', '_') + latest = data['versions'][0] - if each.ui_section in ['hooks', 'extensions']: - v = each.ui_active + c.update_url = _update_url + c.latest_data = latest + c.latest_ver = latest['version'] + c.cur_ver = __version__ + c.should_upgrade = False - settings[each.ui_section + '_' + k] = v - return settings + if NormalizedVersion(c.latest_ver) > NormalizedVersion(c.cur_ver): + c.should_upgrade = True + c.important_notices = latest['general'] + + return render('admin/settings/settings_system_update.html'), diff --git a/kallithea/controllers/admin/user_groups.py b/kallithea/controllers/admin/user_groups.py new file mode 100644 --- /dev/null +++ b/kallithea/controllers/admin/user_groups.py @@ -0,0 +1,463 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.controllers.admin.users_groups +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +User Groups crud controller for pylons + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jan 25, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import logging +import traceback +import formencode + +from formencode import htmlfill +from pylons import request, session, tmpl_context as c, url, config +from pylons.controllers.util import abort, redirect +from pylons.i18n.translation import _ + +from sqlalchemy.orm import joinedload +from sqlalchemy.sql.expression import func +from webob.exc import HTTPInternalServerError + +import kallithea +from kallithea.lib import helpers as h +from kallithea.lib.exceptions import UserGroupsAssignedException,\ + RepoGroupAssignmentError +from kallithea.lib.utils2 import safe_unicode, str2bool, safe_int +from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator,\ + HasUserGroupPermissionAnyDecorator, HasPermissionAnyDecorator +from kallithea.lib.base import BaseController, render +from kallithea.model.scm import UserGroupList +from kallithea.model.user_group import UserGroupModel +from kallithea.model.repo import RepoModel +from kallithea.model.db import User, UserGroup, UserGroupToPerm,\ + UserGroupRepoToPerm, UserGroupRepoGroupToPerm +from kallithea.model.forms import UserGroupForm, UserGroupPermsForm,\ + CustomDefaultPermissionsForm +from kallithea.model.meta import Session +from kallithea.lib.utils import action_logger +from kallithea.lib.compat import json + +log = logging.getLogger(__name__) + + +class UserGroupsController(BaseController): + """REST Controller styled on the Atom Publishing Protocol""" + + @LoginRequired() + def __before__(self): + super(UserGroupsController, self).__before__() + c.available_permissions = config['available_permissions'] + + def __load_data(self, user_group_id): + c.group_members_obj = sorted((x.user for x in c.user_group.members), + key=lambda u: u.username.lower()) + + c.group_members = [(x.user_id, x.username) for x in c.group_members_obj] + c.available_members = sorted(((x.user_id, x.username) for x in + User.query().all()), + key=lambda u: u[1].lower()) + + def __load_defaults(self, user_group_id): + """ + Load defaults settings for edit, and update + + :param user_group_id: + """ + user_group = UserGroup.get_or_404(user_group_id) + data = user_group.get_dict() + return data + + def index(self, format='html'): + """GET /users_groups: All items in the collection""" + # url('users_groups') + _list = UserGroup.query()\ + .order_by(func.lower(UserGroup.users_group_name))\ + .all() + group_iter = UserGroupList(_list, perm_set=['usergroup.admin']) + user_groups_data = [] + total_records = len(group_iter) + _tmpl_lookup = kallithea.CONFIG['pylons.app_globals'].mako_lookup + template = _tmpl_lookup.get_template('data_table/_dt_elements.html') + + user_group_name = lambda user_group_id, user_group_name: ( + template.get_def("user_group_name") + .render(user_group_id, user_group_name, _=_, h=h, c=c) + ) + user_group_actions = lambda user_group_id, user_group_name: ( + template.get_def("user_group_actions") + .render(user_group_id, user_group_name, _=_, h=h, c=c) + ) + for user_gr in group_iter: + + user_groups_data.append({ + "raw_name": user_gr.users_group_name, + "group_name": user_group_name(user_gr.users_group_id, + user_gr.users_group_name), + "desc": user_gr.user_group_description, + "members": len(user_gr.members), + "active": h.boolicon(user_gr.users_group_active), + "owner": h.person(user_gr.user.username), + "action": user_group_actions(user_gr.users_group_id, user_gr.users_group_name) + }) + + c.data = json.dumps({ + "totalRecords": total_records, + "startIndex": 0, + "sort": None, + "dir": "asc", + "records": user_groups_data + }) + + return render('admin/user_groups/user_groups.html') + + @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true') + def create(self): + """POST /users_groups: Create a new item""" + # url('users_groups') + + users_group_form = UserGroupForm()() + try: + form_result = users_group_form.to_python(dict(request.POST)) + UserGroupModel().create(name=form_result['users_group_name'], + description=form_result['user_group_description'], + owner=self.authuser.user_id, + active=form_result['users_group_active']) + + gr = form_result['users_group_name'] + action_logger(self.authuser, + 'admin_created_users_group:%s' % gr, + None, self.ip_addr, self.sa) + h.flash(_('Created user group %s') % gr, category='success') + Session().commit() + except formencode.Invalid, errors: + return htmlfill.render( + render('admin/user_groups/user_group_add.html'), + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8") + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during creation of user group %s') \ + % request.POST.get('users_group_name'), category='error') + + return redirect(url('users_groups')) + + @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true') + def new(self, format='html'): + """GET /user_groups/new: Form to create a new item""" + # url('new_users_group') + return render('admin/user_groups/user_group_add.html') + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def update(self, id): + """PUT /user_groups/id: Update an existing item""" + # Forms posted to this method should contain a hidden field: + # + # Or using helpers: + # h.form(url('users_group', id=ID), + # method='put') + # url('users_group', id=ID) + + c.user_group = UserGroup.get_or_404(id) + c.active = 'settings' + self.__load_data(id) + + available_members = [safe_unicode(x[0]) for x in c.available_members] + + users_group_form = UserGroupForm(edit=True, + old_data=c.user_group.get_dict(), + available_members=available_members)() + + try: + form_result = users_group_form.to_python(request.POST) + UserGroupModel().update(c.user_group, form_result) + gr = form_result['users_group_name'] + action_logger(self.authuser, + 'admin_updated_users_group:%s' % gr, + None, self.ip_addr, self.sa) + h.flash(_('Updated user group %s') % gr, category='success') + Session().commit() + except formencode.Invalid, errors: + ug_model = UserGroupModel() + defaults = errors.value + e = errors.error_dict or {} + defaults.update({ + 'create_repo_perm': ug_model.has_perm(id, + 'hg.create.repository'), + 'fork_repo_perm': ug_model.has_perm(id, + 'hg.fork.repository'), + '_method': 'put' + }) + + return htmlfill.render( + render('admin/user_groups/user_group_edit.html'), + defaults=defaults, + errors=e, + prefix_error=False, + encoding="UTF-8") + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during update of user group %s') \ + % request.POST.get('users_group_name'), category='error') + + return redirect(url('edit_users_group', id=id)) + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def delete(self, id): + """DELETE /user_groups/id: Delete an existing item""" + # Forms posted to this method should contain a hidden field: + # + # Or using helpers: + # h.form(url('users_group', id=ID), + # method='delete') + # url('users_group', id=ID) + usr_gr = UserGroup.get_or_404(id) + try: + UserGroupModel().delete(usr_gr) + Session().commit() + h.flash(_('Successfully deleted user group'), category='success') + except UserGroupsAssignedException, e: + h.flash(e, category='error') + except Exception: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during deletion of user group'), + category='error') + return redirect(url('users_groups')) + + def show(self, id, format='html'): + """GET /user_groups/id: Show a specific item""" + # url('users_group', id=ID) + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def edit(self, id, format='html'): + """GET /user_groups/id/edit: Form to edit an existing item""" + # url('edit_users_group', id=ID) + + c.user_group = UserGroup.get_or_404(id) + c.active = 'settings' + self.__load_data(id) + + defaults = self.__load_defaults(id) + + return htmlfill.render( + render('admin/user_groups/user_group_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False + ) + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def edit_perms(self, id): + c.user_group = UserGroup.get_or_404(id) + c.active = 'perms' + + repo_model = RepoModel() + c.users_array = repo_model.get_users_js() + c.user_groups_array = repo_model.get_user_groups_js() + + defaults = {} + # fill user group users + for p in c.user_group.user_user_group_to_perm: + defaults.update({'u_perm_%s' % p.user.username: + p.permission.permission_name}) + + for p in c.user_group.user_group_user_group_to_perm: + defaults.update({'g_perm_%s' % p.user_group.users_group_name: + p.permission.permission_name}) + + return htmlfill.render( + render('admin/user_groups/user_group_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False + ) + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def update_perms(self, id): + """ + grant permission for given usergroup + + :param id: + """ + user_group = UserGroup.get_or_404(id) + form = UserGroupPermsForm()().to_python(request.POST) + + # set the permissions ! + try: + UserGroupModel()._update_permissions(user_group, form['perms_new'], + form['perms_updates']) + except RepoGroupAssignmentError: + h.flash(_('Target group cannot be the same'), category='error') + return redirect(url('edit_user_group_perms', id=id)) + #TODO: implement this + #action_logger(self.authuser, 'admin_changed_repo_permissions', + # repo_name, self.ip_addr, self.sa) + Session().commit() + h.flash(_('User Group permissions updated'), category='success') + return redirect(url('edit_user_group_perms', id=id)) + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def delete_perms(self, id): + """ + DELETE an existing repository group permission user + + :param group_name: + """ + try: + obj_type = request.POST.get('obj_type') + obj_id = None + if obj_type == 'user': + obj_id = safe_int(request.POST.get('user_id')) + elif obj_type == 'user_group': + obj_id = safe_int(request.POST.get('user_group_id')) + + if not c.authuser.is_admin: + if obj_type == 'user' and c.authuser.user_id == obj_id: + msg = _('Cannot revoke permission for yourself as admin') + h.flash(msg, category='warning') + raise Exception('revoke admin permission on self') + if obj_type == 'user': + UserGroupModel().revoke_user_permission(user_group=id, + user=obj_id) + elif obj_type == 'user_group': + UserGroupModel().revoke_user_group_permission(target_user_group=id, + user_group=obj_id) + Session().commit() + except Exception: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during revoking of permission'), + category='error') + raise HTTPInternalServerError() + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def edit_default_perms(self, id): + c.user_group = UserGroup.get_or_404(id) + c.active = 'default_perms' + + permissions = { + 'repositories': {}, + 'repositories_groups': {} + } + ugroup_repo_perms = UserGroupRepoToPerm.query()\ + .options(joinedload(UserGroupRepoToPerm.permission))\ + .options(joinedload(UserGroupRepoToPerm.repository))\ + .filter(UserGroupRepoToPerm.users_group_id == id)\ + .all() + + for gr in ugroup_repo_perms: + permissions['repositories'][gr.repository.repo_name] \ + = gr.permission.permission_name + + ugroup_group_perms = UserGroupRepoGroupToPerm.query()\ + .options(joinedload(UserGroupRepoGroupToPerm.permission))\ + .options(joinedload(UserGroupRepoGroupToPerm.group))\ + .filter(UserGroupRepoGroupToPerm.users_group_id == id)\ + .all() + + for gr in ugroup_group_perms: + permissions['repositories_groups'][gr.group.group_name] \ + = gr.permission.permission_name + c.permissions = permissions + + ug_model = UserGroupModel() + + defaults = c.user_group.get_dict() + defaults.update({ + 'create_repo_perm': ug_model.has_perm(c.user_group, + 'hg.create.repository'), + 'create_user_group_perm': ug_model.has_perm(c.user_group, + 'hg.usergroup.create.true'), + 'fork_repo_perm': ug_model.has_perm(c.user_group, + 'hg.fork.repository'), + }) + + return htmlfill.render( + render('admin/user_groups/user_group_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False + ) + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def update_default_perms(self, id): + """PUT /users_perm/id: Update an existing item""" + # url('users_group_perm', id=ID, method='put') + + user_group = UserGroup.get_or_404(id) + + try: + form = CustomDefaultPermissionsForm()() + form_result = form.to_python(request.POST) + + inherit_perms = form_result['inherit_default_permissions'] + user_group.inherit_default_permissions = inherit_perms + Session().add(user_group) + usergroup_model = UserGroupModel() + + defs = UserGroupToPerm.query()\ + .filter(UserGroupToPerm.users_group == user_group)\ + .all() + for ug in defs: + Session().delete(ug) + + if form_result['create_repo_perm']: + usergroup_model.grant_perm(id, 'hg.create.repository') + else: + usergroup_model.grant_perm(id, 'hg.create.none') + if form_result['create_user_group_perm']: + usergroup_model.grant_perm(id, 'hg.usergroup.create.true') + else: + usergroup_model.grant_perm(id, 'hg.usergroup.create.false') + if form_result['fork_repo_perm']: + usergroup_model.grant_perm(id, 'hg.fork.repository') + else: + usergroup_model.grant_perm(id, 'hg.fork.none') + + h.flash(_("Updated permissions"), category='success') + Session().commit() + except Exception: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during permissions saving'), + category='error') + + return redirect(url('edit_user_group_default_perms', id=id)) + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def edit_advanced(self, id): + c.user_group = UserGroup.get_or_404(id) + c.active = 'advanced' + c.group_members_obj = sorted((x.user for x in c.user_group.members), + key=lambda u: u.username.lower()) + return render('admin/user_groups/user_group_edit.html') + + + @HasUserGroupPermissionAnyDecorator('usergroup.admin') + def edit_members(self, id): + c.user_group = UserGroup.get_or_404(id) + c.active = 'members' + c.group_members_obj = sorted((x.user for x in c.user_group.members), + key=lambda u: u.username.lower()) + + c.group_members = [(x.user_id, x.username) for x in c.group_members_obj] + return render('admin/user_groups/user_group_edit.html') diff --git a/rhodecode/controllers/admin/users.py b/kallithea/controllers/admin/users.py rename from rhodecode/controllers/admin/users.py rename to kallithea/controllers/admin/users.py --- a/rhodecode/controllers/admin/users.py +++ b/kallithea/controllers/admin/users.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.admin.users - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Users crud controller for pylons - - :created_on: Apr 4, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.admin.users +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Users crud controller for pylons + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 4, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import logging import traceback @@ -32,31 +34,32 @@ from formencode import htmlfill from pylons import request, session, tmpl_context as c, url, config from pylons.controllers.util import redirect from pylons.i18n.translation import _ +from sqlalchemy.sql.expression import func -import rhodecode -from rhodecode.lib.exceptions import DefaultUserException, \ +import kallithea +from kallithea.lib.exceptions import DefaultUserException, \ UserOwnsReposException, UserCreationError -from rhodecode.lib import helpers as h -from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \ - AuthUser -from rhodecode.lib.base import BaseController, render +from kallithea.lib import helpers as h +from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator, \ + AuthUser, generate_api_key +import kallithea.lib.auth_modules.auth_internal +from kallithea.lib import auth_modules +from kallithea.lib.base import BaseController, render +from kallithea.model.api_key import ApiKeyModel -from rhodecode.model.db import User, UserEmailMap, UserIpMap, UserToPerm -from rhodecode.model.forms import UserForm, CustomDefaultPermissionsForm -from rhodecode.model.user import UserModel -from rhodecode.model.meta import Session -from rhodecode.lib.utils import action_logger -from rhodecode.lib.compat import json -from rhodecode.lib.utils2 import datetime_to_time, str2bool +from kallithea.model.db import User, UserEmailMap, UserIpMap, UserToPerm +from kallithea.model.forms import UserForm, CustomDefaultPermissionsForm +from kallithea.model.user import UserModel +from kallithea.model.meta import Session +from kallithea.lib.utils import action_logger +from kallithea.lib.compat import json +from kallithea.lib.utils2 import datetime_to_time, str2bool, safe_int log = logging.getLogger(__name__) class UsersController(BaseController): """REST Controller styled on the Atom Publishing Protocol""" - # To properly map this controller, ensure your config/routing.py - # file has a resource setup: - # map.resource('user', 'users') @LoginRequired() @HasPermissionAllDecorator('hg.admin') @@ -70,18 +73,19 @@ class UsersController(BaseController): c.users_list = User.query().order_by(User.username)\ .filter(User.username != User.DEFAULT_USER)\ + .order_by(func.lower(User.username))\ .all() users_data = [] total_records = len(c.users_list) - _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup + _tmpl_lookup = kallithea.CONFIG['pylons.app_globals'].mako_lookup template = _tmpl_lookup.get_template('data_table/_dt_elements.html') grav_tmpl = lambda user_email, size: ( template.get_def("user_gravatar") .render(user_email, size, _=_, h=h, c=c)) - user_lnk = lambda user_id, username: ( + username = lambda user_id, username: ( template.get_def("user_name") .render(user_id, username, _=_, h=h, c=c)) @@ -92,16 +96,17 @@ class UsersController(BaseController): for user in c.users_list: users_data.append({ - "gravatar": grav_tmpl(user. email, 24), - "raw_username": user.username, - "username": user_lnk(user.user_id, user.username), + "gravatar": grav_tmpl(user. email, 20), + "raw_name": user.username, + "username": username(user.user_id, user.username), "firstname": user.name, "lastname": user.lastname, "last_login": h.fmt_date(user.last_login), "last_login_raw": datetime_to_time(user.last_login), "active": h.boolicon(user.active), "admin": h.boolicon(user.admin), - "ldap": h.boolicon(bool(user.ldap_dn)), + "extern_type": user.extern_type, + "extern_name": user.extern_name, "action": user_actions(user.user_id, user.username), }) @@ -118,14 +123,14 @@ class UsersController(BaseController): def create(self): """POST /users: Create a new item""" # url('users') - + c.default_extern_type = auth_modules.auth_internal.KallitheaAuthPlugin.name user_model = UserModel() user_form = UserForm()() try: form_result = user_form.to_python(dict(request.POST)) user_model.create(form_result) usr = form_result['username'] - action_logger(self.rhodecode_user, 'admin_created_user:%s' % usr, + action_logger(self.authuser, 'admin_created_user:%s' % usr, None, self.ip_addr, self.sa) h.flash(_('Created user %s') % usr, category='success') @@ -148,6 +153,7 @@ class UsersController(BaseController): def new(self, format='html'): """GET /users/new: Form to create a new item""" # url('new_user') + c.default_extern_type = auth_modules.auth_internal.KallitheaAuthPlugin.name return render('admin/users/user_add.html') def update(self, id): @@ -158,34 +164,35 @@ class UsersController(BaseController): # h.form(url('update_user', id=ID), # method='put') # url('user', id=ID) + c.active = 'profile' user_model = UserModel() c.user = user_model.get(id) - c.ldap_dn = c.user.ldap_dn + c.extern_type = c.user.extern_type + c.extern_name = c.user.extern_name c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr) _form = UserForm(edit=True, old_data={'user_id': id, 'email': c.user.email})() form_result = {} try: form_result = _form.to_python(dict(request.POST)) - skip_attrs = [] - if c.ldap_dn: - #forbid updating username for ldap accounts - skip_attrs = ['username'] + skip_attrs = ['extern_type', 'extern_name'] + #TODO: plugin should define if username can be updated + if c.extern_type != kallithea.EXTERN_TYPE_INTERNAL: + # forbid updating username for external accounts + skip_attrs.append('username') + user_model.update(id, form_result, skip_attrs=skip_attrs) usr = form_result['username'] - action_logger(self.rhodecode_user, 'admin_updated_user:%s' % usr, + action_logger(self.authuser, 'admin_updated_user:%s' % usr, None, self.ip_addr, self.sa) h.flash(_('User updated successfully'), category='success') Session().commit() except formencode.Invalid, errors: - c.user_email_map = UserEmailMap.query()\ - .filter(UserEmailMap.user == c.user).all() - c.user_ip_map = UserIpMap.query()\ - .filter(UserIpMap.user == c.user).all() defaults = errors.value e = errors.error_dict or {} defaults.update({ - 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'), + 'create_repo_perm': user_model.has_perm(id, + 'hg.create.repository'), 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'), '_method': 'put' }) @@ -231,36 +238,132 @@ class UsersController(BaseController): """GET /users/id/edit: Form to edit an existing item""" # url('edit_user', id=ID) c.user = User.get_or_404(id) + if c.user.username == User.DEFAULT_USER: + h.flash(_("You can't edit this user"), category='warning') + return redirect(url('users')) - if c.user.username == 'default': + c.active = 'profile' + c.extern_type = c.user.extern_type + c.extern_name = c.user.extern_name + c.EXTERN_TYPE_INTERNAL = kallithea.EXTERN_TYPE_INTERNAL + c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr) + + defaults = c.user.get_dict() + return htmlfill.render( + render('admin/users/user_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + def edit_advanced(self, id): + c.user = User.get_or_404(id) + if c.user.username == User.DEFAULT_USER: h.flash(_("You can't edit this user"), category='warning') return redirect(url('users')) + c.active = 'advanced' c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr) - c.user.permissions = {} - c.granted_permissions = UserModel().fill_perms(c.user)\ - .permissions['global'] - c.user_email_map = UserEmailMap.query()\ - .filter(UserEmailMap.user == c.user).all() - c.user_ip_map = UserIpMap.query()\ - .filter(UserIpMap.user == c.user).all() + umodel = UserModel() - c.ldap_dn = c.user.ldap_dn defaults = c.user.get_dict() defaults.update({ - 'create_repo_perm': umodel.has_perm(c.user, 'hg.create.repository'), - 'create_user_group_perm': umodel.has_perm(c.user, 'hg.usergroup.create.true'), - 'fork_repo_perm': umodel.has_perm(c.user, 'hg.fork.repository'), + 'create_repo_perm': umodel.has_perm(c.user, 'hg.create.repository'), + 'create_user_group_perm': umodel.has_perm(c.user, + 'hg.usergroup.create.true'), + 'fork_repo_perm': umodel.has_perm(c.user, 'hg.fork.repository'), }) + return htmlfill.render( + render('admin/users/user_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + def edit_api_keys(self, id): + c.user = User.get_or_404(id) + if c.user.username == User.DEFAULT_USER: + h.flash(_("You can't edit this user"), category='warning') + return redirect(url('users')) + + c.active = 'api_keys' + show_expired = True + c.lifetime_values = [ + (str(-1), _('forever')), + (str(5), _('5 minutes')), + (str(60), _('1 hour')), + (str(60 * 24), _('1 day')), + (str(60 * 24 * 30), _('1 month')), + ] + c.lifetime_options = [(c.lifetime_values, _("Lifetime"))] + c.user_api_keys = ApiKeyModel().get_api_keys(c.user.user_id, + show_expired=show_expired) + defaults = c.user.get_dict() return htmlfill.render( render('admin/users/user_edit.html'), defaults=defaults, encoding="UTF-8", - force_defaults=False - ) + force_defaults=False) + + def add_api_key(self, id): + c.user = User.get_or_404(id) + if c.user.username == User.DEFAULT_USER: + h.flash(_("You can't edit this user"), category='warning') + return redirect(url('users')) + + lifetime = safe_int(request.POST.get('lifetime'), -1) + description = request.POST.get('description') + new_api_key = ApiKeyModel().create(c.user.user_id, description, lifetime) + Session().commit() + h.flash(_("Api key successfully created"), category='success') + return redirect(url('edit_user_api_keys', id=c.user.user_id)) + + def delete_api_key(self, id): + c.user = User.get_or_404(id) + if c.user.username == User.DEFAULT_USER: + h.flash(_("You can't edit this user"), category='warning') + return redirect(url('users')) - def update_perm(self, id): + api_key = request.POST.get('del_api_key') + if request.POST.get('del_api_key_builtin'): + user = User.get(c.user.user_id) + if user: + user.api_key = generate_api_key(user.username) + Session().add(user) + Session().commit() + h.flash(_("Api key successfully reset"), category='success') + elif api_key: + ApiKeyModel().delete(api_key, c.user.user_id) + Session().commit() + h.flash(_("Api key successfully deleted"), category='success') + + return redirect(url('edit_user_api_keys', id=c.user.user_id)) + + def update_account(self, id): + pass + + def edit_perms(self, id): + c.user = User.get_or_404(id) + if c.user.username == User.DEFAULT_USER: + h.flash(_("You can't edit this user"), category='warning') + return redirect(url('users')) + + c.active = 'perms' + c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr) + + umodel = UserModel() + defaults = c.user.get_dict() + defaults.update({ + 'create_repo_perm': umodel.has_perm(c.user, 'hg.create.repository'), + 'create_user_group_perm': umodel.has_perm(c.user, + 'hg.usergroup.create.true'), + 'fork_repo_perm': umodel.has_perm(c.user, 'hg.fork.repository'), + }) + return htmlfill.render( + render('admin/users/user_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) + + def update_perms(self, id): """PUT /users_perm/id: Update an existing item""" # url('user_perm', id=ID, method='put') user = User.get_or_404(id) @@ -298,7 +401,24 @@ class UsersController(BaseController): log.error(traceback.format_exc()) h.flash(_('An error occurred during permissions saving'), category='error') - return redirect(url('edit_user', id=id)) + return redirect(url('edit_user_perms', id=id)) + + def edit_emails(self, id): + c.user = User.get_or_404(id) + if c.user.username == User.DEFAULT_USER: + h.flash(_("You can't edit this user"), category='warning') + return redirect(url('users')) + + c.active = 'emails' + c.user_email_map = UserEmailMap.query()\ + .filter(UserEmailMap.user == c.user).all() + + defaults = c.user.get_dict() + return htmlfill.render( + render('admin/users/user_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) def add_email(self, id): """POST /user_emails:Add an existing item""" @@ -318,16 +438,38 @@ class UsersController(BaseController): log.error(traceback.format_exc()) h.flash(_('An error occurred during email saving'), category='error') - return redirect(url('edit_user', id=id)) + return redirect(url('edit_user_emails', id=id)) def delete_email(self, id): """DELETE /user_emails_delete/id: Delete an existing item""" # url('user_emails_delete', id=ID, method='delete') + email_id = request.POST.get('del_email_id') user_model = UserModel() - user_model.delete_extra_email(id, request.POST.get('del_email')) + user_model.delete_extra_email(id, email_id) Session().commit() h.flash(_("Removed email from user"), category='success') - return redirect(url('edit_user', id=id)) + return redirect(url('edit_user_emails', id=id)) + + def edit_ips(self, id): + c.user = User.get_or_404(id) + if c.user.username == User.DEFAULT_USER: + h.flash(_("You can't edit this user"), category='warning') + return redirect(url('users')) + + c.active = 'ips' + c.user_ip_map = UserIpMap.query()\ + .filter(UserIpMap.user == c.user).all() + + c.inherit_default_ips = c.user.inherit_default_permissions + c.default_user_ip_map = UserIpMap.query()\ + .filter(UserIpMap.user == User.get_default_user()).all() + + defaults = c.user.get_dict() + return htmlfill.render( + render('admin/users/user_edit.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=False) def add_ip(self, id): """POST /user_ips:Add an existing item""" @@ -339,7 +481,7 @@ class UsersController(BaseController): try: user_model.add_extra_ip(id, ip) Session().commit() - h.flash(_("Added ip %s to user") % ip, category='success') + h.flash(_("Added ip %s to user whitelist") % ip, category='success') except formencode.Invalid, error: msg = error.error_dict['ip'] h.flash(msg, category='error') @@ -347,17 +489,20 @@ class UsersController(BaseController): log.error(traceback.format_exc()) h.flash(_('An error occurred during ip saving'), category='error') + if 'default_user' in request.POST: - return redirect(url('edit_permission', id='default')) - return redirect(url('edit_user', id=id)) + return redirect(url('admin_permissions_ips')) + return redirect(url('edit_user_ips', id=id)) def delete_ip(self, id): """DELETE /user_ips_delete/id: Delete an existing item""" # url('user_ips_delete', id=ID, method='delete') + ip_id = request.POST.get('del_ip_id') user_model = UserModel() - user_model.delete_extra_ip(id, request.POST.get('del_ip')) + user_model.delete_extra_ip(id, ip_id) Session().commit() - h.flash(_("Removed ip from user"), category='success') + h.flash(_("Removed ip address from user whitelist"), category='success') + if 'default_user' in request.POST: - return redirect(url('edit_permission', id='default')) - return redirect(url('edit_user', id=id)) + return redirect(url('admin_permissions_ips')) + return redirect(url('edit_user_ips', id=id)) diff --git a/rhodecode/controllers/api/__init__.py b/kallithea/controllers/api/__init__.py rename from rhodecode/controllers/api/__init__.py rename to kallithea/controllers/api/__init__.py --- a/rhodecode/controllers/api/__init__.py +++ b/kallithea/controllers/api/__init__.py @@ -1,19 +1,8 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.api - ~~~~~~~~~~~~~~~~~~~~~~~~~ - - JSON RPC controller - - :created_on: Aug 20, 2011 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; version 2 -# of the License or (at your opinion) any later version of the license. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,9 +10,20 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. +# along with this program. If not, see . +""" +kallithea.controllers.api +~~~~~~~~~~~~~~~~~~~~~~~~~ + +JSON RPC controller + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Aug 20, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import inspect import logging @@ -35,15 +35,14 @@ import time from paste.response import replace_header from pylons.controllers import WSGIController -from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \ -HTTPBadRequest, HTTPError +from webob.exc import HTTPError -from rhodecode.model.db import User -from rhodecode.model import meta -from rhodecode.lib.compat import izip_longest, json -from rhodecode.lib.auth import AuthUser -from rhodecode.lib.base import _get_ip_addr, _get_access_path -from rhodecode.lib.utils2 import safe_unicode +from kallithea.model.db import User +from kallithea.model import meta +from kallithea.lib.compat import izip_longest, json +from kallithea.lib.auth import AuthUser +from kallithea.lib.base import _get_ip_addr as _get_ip, _get_access_path +from kallithea.lib.utils2 import safe_unicode, safe_str log = logging.getLogger('JSONRPC') @@ -55,18 +54,22 @@ class JSONRPCError(BaseException): super(JSONRPCError, self).__init__() def __str__(self): - return str(self.message) + return safe_str(self.message) def jsonrpc_error(message, retid=None, code=None): """ Generate a Response object with a JSON-RPC error body + + :param code: + :param retid: + :param message: """ from pylons.controllers.util import Response return Response( - body=json.dumps(dict(id=retid, result=None, error=message)), - status=code, - content_type='application/json' + body=json.dumps(dict(id=retid, result=None, error=message)), + status=code, + content_type='application/json' ) @@ -85,7 +88,7 @@ class JSONRPCController(WSGIController): """ def _get_ip_addr(self, environ): - return _get_ip_addr(environ) + return _get_ip(environ) def _get_method_args(self): """ @@ -99,6 +102,12 @@ class JSONRPCController(WSGIController): Parse the request body as JSON, look up the method on the controller and if it exists, dispatch to it. """ + try: + return self._handle_request(environ, start_response) + finally: + meta.Session.remove() + + def _handle_request(self, environ, start_response): start = time.time() ip_addr = self.ip_addr = self._get_ip_addr(environ) self._req_id = None @@ -119,12 +128,12 @@ class JSONRPCController(WSGIController): raw_body = environ['wsgi.input'].read(length) try: - json_body = json.loads(urllib.unquote_plus(raw_body)) + json_body = json.loads(raw_body) except ValueError, e: # catch JSON errors Here return jsonrpc_error(retid=self._req_id, - message="JSON parse error ERR:%s RAW:%r" \ - % (e, urllib.unquote_plus(raw_body))) + message="JSON parse error ERR:%s RAW:%r" + % (e, raw_body)) # check AUTH based on API KEY try: @@ -154,9 +163,9 @@ class JSONRPCController(WSGIController): auth_u = AuthUser(u.user_id, self._req_api_key, ip_addr=ip_addr) if not auth_u.ip_allowed: return jsonrpc_error(retid=self._req_id, - message='request from IP:%s not allowed' % (ip_addr)) + message='request from IP:%s not allowed' % (ip_addr,)) else: - log.info('Access for IP:%s allowed' % (ip_addr)) + log.info('Access for IP:%s allowed' % (ip_addr,)) except Exception, e: return jsonrpc_error(retid=self._req_id, @@ -182,8 +191,8 @@ class JSONRPCController(WSGIController): # this is little trick to inject logged in user for # perms decorators to work they expect the controller class to have - # rhodecode_user attribute set - self.rhodecode_user = auth_u + # authuser attribute set + self.authuser = auth_u # This attribute will need to be first param of a method that uses # api_key, which is translated to instance of user at that name @@ -206,7 +215,7 @@ class JSONRPCController(WSGIController): # skip the required param check if it's default value is # NotImplementedType (default_empty) - if (default == default_empty and arg not in self._request_params): + if default == default_empty and arg not in self._request_params: return jsonrpc_error( retid=self._req_id, message=( @@ -237,7 +246,7 @@ class JSONRPCController(WSGIController): replace_header(headers, 'Content-Type', 'application/json') start_response(status[0], headers, exc_info[0]) log.info('IP: %s Request to %s time: %.3fs' % ( - _get_ip_addr(environ), + self._get_ip_addr(environ), safe_unicode(_get_access_path(environ)), time.time() - start) ) return output @@ -246,24 +255,23 @@ class JSONRPCController(WSGIController): """ Implement dispatch interface specified by WSGIController """ + raw_response = '' try: raw_response = self._inspect_call(self._func) if isinstance(raw_response, HTTPError): self._error = str(raw_response) except JSONRPCError, e: - self._error = str(e) + self._error = safe_str(e) except Exception, e: - log.error('Encountered unhandled exception: %s' \ - % traceback.format_exc()) + log.error('Encountered unhandled exception: %s' + % (traceback.format_exc(),)) json_exc = JSONRPCError('Internal server error') - self._error = str(json_exc) + self._error = safe_str(json_exc) if self._error is not None: raw_response = None - response = dict(id=self._req_id, result=raw_response, - error=self._error) - + response = dict(id=self._req_id, result=raw_response, error=self._error) try: return json.dumps(response) except TypeError, e: @@ -280,7 +288,7 @@ class JSONRPCController(WSGIController): """ Return method named by `self._req_method` in controller if able """ - log.debug('Trying to find JSON-RPC method: %s' % self._req_method) + log.debug('Trying to find JSON-RPC method: %s' % (self._req_method,)) if self._req_method.startswith('_'): raise AttributeError("Method not allowed") @@ -293,4 +301,4 @@ class JSONRPCController(WSGIController): if isinstance(func, types.MethodType): return func else: - raise AttributeError("No such method: %s" % self._req_method) + raise AttributeError("No such method: %s" % (self._req_method,)) diff --git a/rhodecode/controllers/api/api.py b/kallithea/controllers/api/api.py rename from rhodecode/controllers/api/api.py rename to kallithea/controllers/api/api.py --- a/rhodecode/controllers/api/api.py +++ b/kallithea/controllers/api/api.py @@ -1,19 +1,8 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.api - ~~~~~~~~~~~~~~~~~~~~~~~~~ - - API controller for RhodeCode - - :created_on: Aug 20, 2011 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; version 2 -# of the License or (at your opinion) any later version of the license. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,31 +10,49 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. +# along with this program. If not, see . +""" +kallithea.controllers.api +~~~~~~~~~~~~~~~~~~~~~~~~~ + +API controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Aug 20, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import time import traceback import logging +from sqlalchemy import or_ -from rhodecode.controllers.api import JSONRPCController, JSONRPCError -from rhodecode.lib.auth import PasswordGenerator, AuthUser, \ - HasPermissionAllDecorator, HasPermissionAnyDecorator, \ - HasPermissionAnyApi, HasRepoPermissionAnyApi -from rhodecode.lib.utils import map_groups, repo2db_mapper -from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_int -from rhodecode.model.meta import Session -from rhodecode.model.scm import ScmModel -from rhodecode.model.repo import RepoModel -from rhodecode.model.user import UserModel -from rhodecode.model.users_group import UserGroupModel -from rhodecode.model.repos_group import ReposGroupModel -from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap,\ - Permission, User, Gist -from rhodecode.lib.compat import json -from rhodecode.lib.exceptions import DefaultUserException -from rhodecode.model.gist import GistModel +from kallithea import EXTERN_TYPE_INTERNAL +from kallithea.controllers.api import JSONRPCController, JSONRPCError +from kallithea.lib.auth import ( + PasswordGenerator, AuthUser, HasPermissionAllDecorator, + HasPermissionAnyDecorator, HasPermissionAnyApi, HasRepoPermissionAnyApi, + HasRepoGroupPermissionAnyApi, HasUserGroupPermissionAny) +from kallithea.lib.utils import map_groups, repo2db_mapper +from kallithea.lib.utils2 import ( + str2bool, time_to_datetime, safe_int, Optional, OAttr) +from kallithea.model.meta import Session +from kallithea.model.repo_group import RepoGroupModel +from kallithea.model.scm import ScmModel, UserGroupList +from kallithea.model.repo import RepoModel +from kallithea.model.user import UserModel +from kallithea.model.user_group import UserGroupModel +from kallithea.model.gist import GistModel +from kallithea.model.db import ( + Repository, Setting, UserIpMap, Permission, User, Gist, + RepoGroup) +from kallithea.lib.compat import json +from kallithea.lib.exceptions import ( + DefaultUserException, UserGroupsAssignedException) log = logging.getLogger(__name__) @@ -59,56 +66,6 @@ def store_update(updates, attr, name): updates[name] = attr -class OptionalAttr(object): - """ - Special Optional Option that defines other attribute - """ - def __init__(self, attr_name): - self.attr_name = attr_name - - def __repr__(self): - return '' % self.attr_name - - def __call__(self): - return self -#alias -OAttr = OptionalAttr - - -class Optional(object): - """ - Defines an optional parameter:: - - param = param.getval() if isinstance(param, Optional) else param - param = param() if isinstance(param, Optional) else param - - is equivalent of:: - - param = Optional.extract(param) - - """ - def __init__(self, type_): - self.type_ = type_ - - def __repr__(self): - return '' % self.type_.__repr__() - - def __call__(self): - return self.getval() - - def getval(self): - """ - returns value from this Optional instance - """ - return self.type_ - - @classmethod - def extract(cls, val): - if isinstance(val, cls): - return val.getval() - return val - - def get_user_or_error(userid): """ Get user by id or name or return JsonRPCError if not found @@ -117,7 +74,7 @@ def get_user_or_error(userid): """ user = UserModel().get_user(userid) if user is None: - raise JSONRPCError("user `%s` does not exist" % userid) + raise JSONRPCError("user `%s` does not exist" % (userid,)) return user @@ -129,7 +86,7 @@ def get_repo_or_error(repoid): """ repo = RepoModel().get_repo(repoid) if repo is None: - raise JSONRPCError('repository `%s` does not exist' % (repoid)) + raise JSONRPCError('repository `%s` does not exist' % (repoid,)) return repo @@ -139,68 +96,114 @@ def get_repo_group_or_error(repogroupid) :param repogroupid: """ - repo_group = ReposGroupModel()._get_repo_group(repogroupid) + repo_group = RepoGroupModel()._get_repo_group(repogroupid) if repo_group is None: raise JSONRPCError( 'repository group `%s` does not exist' % (repogroupid,)) return repo_group -def get_users_group_or_error(usersgroupid): +def get_user_group_or_error(usergroupid): """ Get user group by id or name or return JsonRPCError if not found - :param userid: + :param usergroupid: """ - users_group = UserGroupModel().get_group(usersgroupid) - if users_group is None: - raise JSONRPCError('user group `%s` does not exist' % usersgroupid) - return users_group + user_group = UserGroupModel().get_group(usergroupid) + if user_group is None: + raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) + return user_group -def get_perm_or_error(permid): +def get_perm_or_error(permid, prefix=None): """ Get permission by id or name or return JsonRPCError if not found - :param userid: + :param permid: """ perm = Permission.get_by_key(permid) if perm is None: - raise JSONRPCError('permission `%s` does not exist' % (permid)) + raise JSONRPCError('permission `%s` does not exist' % (permid,)) + if prefix: + if not perm.permission_name.startswith(prefix): + raise JSONRPCError('permission `%s` is invalid, ' + 'should start with %s' % (permid, prefix)) return perm +def get_gist_or_error(gistid): + """ + Get gist by id or gist_access_id or return JsonRPCError if not found + + :param gistid: + """ + gist = GistModel().get_gist(gistid) + if gist is None: + raise JSONRPCError('gist `%s` does not exist' % (gistid,)) + return gist + + class ApiController(JSONRPCController): """ API Controller + Each method takes USER as first argument. This is then, based on given + API_KEY propagated as instance of user object who's making the call. - Each method needs to have USER as argument this is then based on given - API_KEY propagated as instance of user object + example function:: - Preferably this should be first argument also - + def func(apiuser,arg1, arg2,...): + pass Each function should also **raise** JSONRPCError for any - errors that happens + errors that happens. """ @HasPermissionAllDecorator('hg.admin') + def test(self, apiuser, args): + return args + + @HasPermissionAllDecorator('hg.admin') def pull(self, apiuser, repoid): """ - Dispatch pull action on given repo + Triggers a pull from remote location on given repo. Can be used to + automatically keep remote repos up to date. This command can be executed + only using api_key belonging to user with admin rights + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int + + OUTPUT:: - :param apiuser: - :param repoid: + id : + result : { + "msg": "Pulled from ``" + "repository": "" + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + "Unable to pull changes from ``" + } + """ repo = get_repo_or_error(repoid) try: ScmModel().pull_changes(repo.repo_name, - self.rhodecode_user.username) - return 'Pulled from `%s`' % repo.repo_name + self.authuser.username) + return dict( + msg='Pulled from `%s`' % repo.repo_name, + repository=repo.repo_name + ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( @@ -210,12 +213,34 @@ class ApiController(JSONRPCController): @HasPermissionAllDecorator('hg.admin') def rescan_repos(self, apiuser, remove_obsolete=Optional(False)): """ - Dispatch rescan repositories action. If remove_obsolete is set + Triggers rescan repositories action. If remove_obsolete is set than also delete repos that are in database but not in the filesystem. - aka "clean zombies" + aka "clean zombies". This command can be executed only using api_key + belonging to user with admin rights. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param remove_obsolete: deletes repositories from + database that are not found on the filesystem + :type remove_obsolete: Optional(bool) + + OUTPUT:: - :param apiuser: - :param remove_obsolete: + id : + result : { + 'added': [,...] + 'removed': [,...] + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + 'Error occurred during rescan repositories action' + } + """ try: @@ -231,22 +256,47 @@ class ApiController(JSONRPCController): def invalidate_cache(self, apiuser, repoid): """ - Dispatch cache invalidation action on given repo + Invalidate cache for repository. + This command can be executed only using api_key belonging to user with admin + rights or regular user that have write or admin or write access to repository. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int + + OUTPUT:: - :param apiuser: - :param repoid: + id : + result : { + 'msg': Cache for repository `` was invalidated, + 'repository': + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + 'Error occurred during cache invalidation action' + } + """ repo = get_repo_or_error(repoid) if not HasPermissionAnyApi('hg.admin')(user=apiuser): # check if we have admin permission for this repo ! - if HasRepoPermissionAnyApi('repository.admin', - 'repository.write')(user=apiuser, - repo_name=repo.repo_name) is False: - raise JSONRPCError('repository `%s` does not exist' % (repoid)) + if not HasRepoPermissionAnyApi('repository.admin', + 'repository.write')( + user=apiuser, repo_name=repo.repo_name): + raise JSONRPCError('repository `%s` does not exist' % (repoid,)) try: ScmModel().mark_for_invalidation(repo.repo_name) - return ('Caches of repository `%s` was invalidated' % repoid) + return dict( + msg='Cache for repository `%s` was invalidated' % (repoid,), + repository=repo.repo_name + ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( @@ -257,14 +307,47 @@ class ApiController(JSONRPCController): def lock(self, apiuser, repoid, locked=Optional(None), userid=Optional(OAttr('apiuser'))): """ - Set locking state on particular repository by given user, if - this command is runned by non-admin account userid is set to user - who is calling this method + Set locking state on given repository by given user. If userid param + is skipped, then it is set to id of user whos calling this method. + If locked param is skipped then function shows current lock state of + given repo. This command can be executed only using api_key belonging + to user with admin rights or regular user that have admin or write + access to repository. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int + :param locked: lock state to be set + :type locked: Optional(bool) + :param userid: set lock as user + :type userid: Optional(str or int) + + OUTPUT:: - :param apiuser: - :param repoid: - :param userid: - :param locked: + id : + result : { + 'repo': '', + 'locked': , + 'locked_since': , + 'locked_by': , + 'lock_state_changed': , + 'msg': 'Repo `` locked by `` on .' + or + 'msg': 'Repo `` not locked.' + or + 'msg': 'User `` set lock state for repo `` to ``' + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + 'Error occurred locking repository `` + } + """ repo = get_repo_or_error(repoid) if HasPermissionAnyApi('hg.admin')(user=apiuser): @@ -272,14 +355,14 @@ class ApiController(JSONRPCController): elif HasRepoPermissionAnyApi('repository.admin', 'repository.write')(user=apiuser, repo_name=repo.repo_name): - #make sure normal user does not pass someone else userid, - #he is not allowed to do that + # make sure normal user does not pass someone else userid, + # he is not allowed to do that if not isinstance(userid, Optional) and userid != apiuser.user_id: raise JSONRPCError( 'userid is not the same as your user' ) else: - raise JSONRPCError('repository `%s` does not exist' % (repoid)) + raise JSONRPCError('repository `%s` does not exist' % (repoid,)) if isinstance(userid, Optional): userid = apiuser.user_id @@ -295,6 +378,7 @@ class ApiController(JSONRPCController): 'locked': False, 'locked_since': None, 'locked_by': None, + 'lock_state_changed': False, 'msg': 'Repo `%s` not locked.' % repo.repo_name } return _d @@ -306,8 +390,9 @@ class ApiController(JSONRPCController): 'locked': True, 'locked_since': time_, 'locked_by': lock_user.username, - 'msg': ('Repo `%s` locked by `%s`. ' - % (repo.repo_name, + 'lock_state_changed': False, + 'msg': ('Repo `%s` locked by `%s` on `%s`.' + % (repo.repo_name, lock_user.username, json.dumps(time_to_datetime(time_)))) } return _d @@ -327,6 +412,7 @@ class ApiController(JSONRPCController): 'locked': locked, 'locked_since': lock_time, 'locked_by': user.username, + 'lock_state_changed': True, 'msg': ('User `%s` set lock state for repo `%s` to `%s`' % (user.username, repo.repo_name, locked)) } @@ -339,28 +425,39 @@ class ApiController(JSONRPCController): def get_locks(self, apiuser, userid=Optional(OAttr('apiuser'))): """ - Get all locks for given userid, if + Get all repositories with locks for given userid, if this command is runned by non-admin account userid is set to user - who is calling this method, thus returning locks for himself + who is calling this method, thus returning locks for himself. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param userid: User to get locks for + :type userid: Optional(str or int) - :param apiuser: - :param userid: + OUTPUT:: + + id : + result : { + [repo_object, repo_object,...] + } + error : null """ if not HasPermissionAnyApi('hg.admin')(user=apiuser): - #make sure normal user does not pass someone else userid, - #he is not allowed to do that + # make sure normal user does not pass someone else userid, + # he is not allowed to do that if not isinstance(userid, Optional) and userid != apiuser.user_id: raise JSONRPCError( 'userid is not the same as your user' ) + ret = [] if isinstance(userid, Optional): user = None else: user = get_user_or_error(userid) - #show all locks + # show all locks for r in Repository.getAll(): userid, time_ = r.locked if time_: @@ -375,31 +472,114 @@ class ApiController(JSONRPCController): return ret @HasPermissionAllDecorator('hg.admin') - def show_ip(self, apiuser, userid): + def get_ip(self, apiuser, userid=Optional(OAttr('apiuser'))): """ - Shows IP address as seen from RhodeCode server, together with all - defined IP addresses for given user + Shows IP address as seen from Kallithea server, together with all + defined IP addresses for given user. If userid is not passed data is + returned for user who's calling this function. + This command can be executed only using api_key belonging to user with + admin rights. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param userid: username to show ips for + :type userid: Optional(str or int) + + OUTPUT:: - :param apiuser: - :param userid: + id : + result : { + "server_ip_addr": "", + "user_ips": [ + { + "ip_addr": "", + "ip_range": ["", ""], + }, + ... + ] + } + """ + if isinstance(userid, Optional): + userid = apiuser.user_id user = get_user_or_error(userid) ips = UserIpMap.query().filter(UserIpMap.user == user).all() return dict( - ip_addr_server=self.ip_addr, + server_ip_addr=self.ip_addr, user_ips=ips ) + # alias for old + show_ip = get_ip + + @HasPermissionAllDecorator('hg.admin') + def get_server_info(self, apiuser): + """ + return server info, including Kallithea version and installed packages + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + + OUTPUT:: + + id : + result : { + 'modules': [,...] + 'py_version': , + 'platform': , + 'kallithea_version': + } + error : null + """ + return Setting.get_server_info() + def get_user(self, apiuser, userid=Optional(OAttr('apiuser'))): - """" - Get a user by username, or userid, if userid is given + """ + Get's an user by username or user_id, Returns empty result if user is + not found. If userid param is skipped it is set to id of user who is + calling this method. This command can be executed only using api_key + belonging to user with admin rights, or regular users that cannot + specify different userid than theirs + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param userid: user to get data for + :type userid: Optional(str or int) + + OUTPUT:: - :param apiuser: - :param userid: + id : + result: None if user does not exist or + { + "user_id" : "", + "api_key" : "", + "api_keys": "[]" + "username" : "", + "firstname": "", + "lastname" : "", + "email" : "", + "emails": "[]", + "ip_addresses": "[,...]", + "active" : "", + "admin" :  "", + "extern_name" : "", + "extern_type" : " + "last_login": "", + "permissions": { + "global": ["hg.create.repository", + "repository.read", + "hg.register.manual_activate"], + "repositories": {"repo1": "repository.none"}, + "repositories_groups": {"Group1": "group.read"} + }, + } + + error: null + """ if not HasPermissionAnyApi('hg.admin')(user=apiuser): - #make sure normal user does not pass someone else userid, - #he is not allowed to do that + # make sure normal user does not pass someone else userid, + # he is not allowed to do that if not isinstance(userid, Optional) and userid != apiuser.user_id: raise JSONRPCError( 'userid is not the same as your user' @@ -415,47 +595,91 @@ class ApiController(JSONRPCController): @HasPermissionAllDecorator('hg.admin') def get_users(self, apiuser): - """" - Get all users + """ + Lists all existing users. This command can be executed only using api_key + belonging to user with admin rights. - :param apiuser: + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + + OUTPUT:: + + id : + result: [, ...] + error: null """ result = [] - users_list = User.query().order_by(User.username)\ - .filter(User.username != User.DEFAULT_USER)\ - .all() + users_list = User.query().order_by(User.username) \ + .filter(User.username != User.DEFAULT_USER) \ + .all() for user in users_list: result.append(user.get_api_data()) return result @HasPermissionAllDecorator('hg.admin') - def create_user(self, apiuser, username, email, password=Optional(None), - firstname=Optional(None), lastname=Optional(None), + def create_user(self, apiuser, username, email, password=Optional(''), + firstname=Optional(''), lastname=Optional(''), active=Optional(True), admin=Optional(False), - ldap_dn=Optional(None)): + extern_name=Optional(EXTERN_TYPE_INTERNAL), + extern_type=Optional(EXTERN_TYPE_INTERNAL)): """ - Create new user + Creates new user. Returns new user object. This command can + be executed only using api_key belonging to user with admin rights. - :param apiuser: - :param username: - :param email: - :param password: - :param firstname: - :param lastname: - :param active: - :param admin: - :param ldap_dn: + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param username: new username + :type username: str or int + :param email: email + :type email: str + :param password: password + :type password: Optional(str) + :param firstname: firstname + :type firstname: Optional(str) + :param lastname: lastname + :type lastname: Optional(str) + :param active: active + :type active: Optional(bool) + :param admin: admin + :type admin: Optional(bool) + :param extern_name: name of extern + :type extern_name: Optional(str) + :param extern_type: extern_type + :type extern_type: Optional(str) + + + OUTPUT:: + + id : + result: { + "msg" : "created new user ``", + "user": + } + error: null + + ERROR OUTPUT:: + + id : + result : null + error : { + "user `` already exist" + or + "email `` already exist" + or + "failed to create user ``" + } + """ if UserModel().get_by_username(username): - raise JSONRPCError("user `%s` already exist" % username) + raise JSONRPCError("user `%s` already exist" % (username,)) if UserModel().get_by_email(email, case_insensitive=True): - raise JSONRPCError("email `%s` already exist" % email) + raise JSONRPCError("email `%s` already exist" % (email,)) - if Optional.extract(ldap_dn): - # generate temporary password if ldap_dn + if Optional.extract(extern_name): + # generate temporary password if user is external password = PasswordGenerator().gen_password(length=8) try: @@ -467,7 +691,8 @@ class ApiController(JSONRPCController): lastname=Optional.extract(lastname), active=Optional.extract(active), admin=Optional.extract(admin), - ldap_dn=Optional.extract(ldap_dn) + extern_type=Optional.extract(extern_type), + extern_name=Optional.extract(extern_name) ) Session().commit() return dict( @@ -476,48 +701,77 @@ class ApiController(JSONRPCController): ) except Exception: log.error(traceback.format_exc()) - raise JSONRPCError('failed to create user `%s`' % username) + raise JSONRPCError('failed to create user `%s`' % (username,)) @HasPermissionAllDecorator('hg.admin') def update_user(self, apiuser, userid, username=Optional(None), - email=Optional(None), firstname=Optional(None), - lastname=Optional(None), active=Optional(None), - admin=Optional(None), ldap_dn=Optional(None), - password=Optional(None)): + email=Optional(None),password=Optional(None), + firstname=Optional(None), lastname=Optional(None), + active=Optional(None), admin=Optional(None), + extern_type=Optional(None), extern_name=Optional(None),): """ - Updates given user + updates given user if such user exists. This command can + be executed only using api_key belonging to user with admin rights. - :param apiuser: - :param userid: - :param username: - :param email: - :param firstname: - :param lastname: - :param active: - :param admin: - :param ldap_dn: - :param password: + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param userid: userid to update + :type userid: str or int + :param username: new username + :type username: str or int + :param email: email + :type email: str + :param password: password + :type password: Optional(str) + :param firstname: firstname + :type firstname: Optional(str) + :param lastname: lastname + :type lastname: Optional(str) + :param active: active + :type active: Optional(bool) + :param admin: admin + :type admin: Optional(bool) + :param extern_name: + :type extern_name: Optional(str) + :param extern_type: + :type extern_type: Optional(str) + + + OUTPUT:: + + id : + result: { + "msg" : "updated user ID: ", + "user": , + } + error: null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to update user ``" + } + """ user = get_user_or_error(userid) - # call function and store only updated arguments + # only non optional arguments will be stored in updates updates = {} - def store_update(attr, name): - if not isinstance(attr, Optional): - updates[name] = attr - try: - store_update(username, 'username') - store_update(password, 'password') - store_update(email, 'email') - store_update(firstname, 'name') - store_update(lastname, 'lastname') - store_update(active, 'active') - store_update(admin, 'admin') - store_update(ldap_dn, 'ldap_dn') + store_update(updates, username, 'username') + store_update(updates, password, 'password') + store_update(updates, email, 'email') + store_update(updates, firstname, 'name') + store_update(updates, lastname, 'lastname') + store_update(updates, active, 'active') + store_update(updates, admin, 'admin') + store_update(updates, extern_name, 'extern_name') + store_update(updates, extern_type, 'extern_type') user = UserModel().update_user(user, **updates) Session().commit() @@ -530,15 +784,36 @@ class ApiController(JSONRPCController): raise JSONRPCError('editing default user is forbidden') except Exception: log.error(traceback.format_exc()) - raise JSONRPCError('failed to update user `%s`' % userid) + raise JSONRPCError('failed to update user `%s`' % (userid,)) @HasPermissionAllDecorator('hg.admin') def delete_user(self, apiuser, userid): - """" - Deletes an user + """ + deletes givenuser if such user exists. This command can + be executed only using api_key belonging to user with admin rights. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param userid: user to delete + :type userid: str or int + + OUTPUT:: - :param apiuser: - :param userid: + id : + result: { + "msg" : "deleted user ID: ", + "user": null + } + error: null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to delete user ID: " + } + """ user = get_user_or_error(userid) @@ -550,57 +825,114 @@ class ApiController(JSONRPCController): user=None ) except Exception: + log.error(traceback.format_exc()) - raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id, - user.username)) + raise JSONRPCError('failed to delete user ID:%s %s' + % (user.user_id, user.username)) - @HasPermissionAllDecorator('hg.admin') - def get_users_group(self, apiuser, usersgroupid): - """" - Get user group by name or id + # permission check inside + def get_user_group(self, apiuser, usergroupid): + """ + Gets an existing user group. This command can be executed only using api_key + belonging to user with admin rights or user who has at least + read access to user group. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param usergroupid: id of user_group to edit + :type usergroupid: str or int + + OUTPUT:: - :param apiuser: - :param usersgroupid: - """ - users_group = get_users_group_or_error(usersgroupid) + id : + result : None if group not exist + { + "users_group_id" : "", + "group_name" : "", + "active": "", + "members" : [,...] + } + error : null - data = users_group.get_api_data() + """ + user_group = get_user_group_or_error(usergroupid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have at least read permission for this user group ! + _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) + if not HasUserGroupPermissionAny(*_perms)( + user=apiuser, user_group_name=user_group.users_group_name): + raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) - members = [] - for user in users_group.members: - user = user.user - members.append(user.get_api_data()) - data['members'] = members + data = user_group.get_api_data() return data - @HasPermissionAllDecorator('hg.admin') - def get_users_groups(self, apiuser): - """" - Get all user groups + # permission check inside + def get_user_groups(self, apiuser): + """ + Lists all existing user groups. This command can be executed only using + api_key belonging to user with admin rights or user who has at least + read access to user group. - :param apiuser: + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + + OUTPUT:: + + id : + result : [,...] + error : null """ result = [] - for users_group in UserGroupModel().get_all(): - result.append(users_group.get_api_data()) + _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) + extras = {'user': apiuser} + for user_group in UserGroupList(UserGroupModel().get_all(), + perm_set=_perms, extra_kwargs=extras): + result.append(user_group.get_api_data()) return result - @HasPermissionAllDecorator('hg.admin') - def create_users_group(self, apiuser, group_name, - owner=Optional(OAttr('apiuser')), - active=Optional(True)): + @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true') + def create_user_group(self, apiuser, group_name, description=Optional(''), + owner=Optional(OAttr('apiuser')), active=Optional(True)): """ - Creates an new usergroup + Creates new user group. This command can be executed only using api_key + belonging to user with admin rights or an user who has create user group + permission + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param group_name: name of new user group + :type group_name: str + :param description: group description + :type description: str + :param owner: owner of group. If not passed apiuser is the owner + :type owner: Optional(str or int) + :param active: group is active + :type active: Optional(bool) + + OUTPUT:: - :param apiuser: - :param group_name: - :param owner: - :param active: + id : + result: { + "msg": "created new user group ``", + "user_group": + } + error: null + + ERROR OUTPUT:: + + id : + result : null + error : { + "user group `` already exist" + or + "failed to create group ``" + } + """ if UserGroupModel().get_by_name(group_name): - raise JSONRPCError("user group `%s` already exist" % group_name) + raise JSONRPCError("user group `%s` already exist" % (group_name,)) try: if isinstance(owner, Optional): @@ -608,36 +940,191 @@ class ApiController(JSONRPCController): owner = get_user_or_error(owner) active = Optional.extract(active) - ug = UserGroupModel().create(name=group_name, - owner=owner, - active=active) + description = Optional.extract(description) + ug = UserGroupModel().create(name=group_name, description=description, + owner=owner, active=active) Session().commit() return dict( msg='created new user group `%s`' % group_name, - users_group=ug.get_api_data() + user_group=ug.get_api_data() + ) + except Exception: + log.error(traceback.format_exc()) + raise JSONRPCError('failed to create group `%s`' % (group_name,)) + + # permission check inside + def update_user_group(self, apiuser, usergroupid, group_name=Optional(''), + description=Optional(''), owner=Optional(None), + active=Optional(True)): + """ + Updates given usergroup. This command can be executed only using api_key + belonging to user with admin rights or an admin of given user group + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param usergroupid: id of user group to update + :type usergroupid: str or int + :param group_name: name of new user group + :type group_name: str + :param description: group description + :type description: str + :param owner: owner of group. + :type owner: Optional(str or int) + :param active: group is active + :type active: Optional(bool) + + OUTPUT:: + + id : + result : { + "msg": 'updated user group ID: ', + "user_group": + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to update user group ``" + } + + """ + user_group = get_user_group_or_error(usergroupid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this user group ! + _perms = ('usergroup.admin',) + if not HasUserGroupPermissionAny(*_perms)( + user=apiuser, user_group_name=user_group.users_group_name): + raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) + + if not isinstance(owner, Optional): + owner = get_user_or_error(owner) + + updates = {} + store_update(updates, group_name, 'users_group_name') + store_update(updates, description, 'user_group_description') + store_update(updates, owner, 'user') + store_update(updates, active, 'users_group_active') + try: + UserGroupModel().update(user_group, updates) + Session().commit() + return dict( + msg='updated user group ID:%s %s' % (user_group.users_group_id, + user_group.users_group_name), + user_group=user_group.get_api_data() ) except Exception: log.error(traceback.format_exc()) - raise JSONRPCError('failed to create group `%s`' % group_name) + raise JSONRPCError('failed to update user group `%s`' % (usergroupid,)) + + # permission check inside + def delete_user_group(self, apiuser, usergroupid): + """ + Delete given user group by user group id or name. + This command can be executed only using api_key + belonging to user with admin rights or an admin of given user group + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param usergroupid: + :type usergroupid: int + + OUTPUT:: + + id : + result : { + "msg": "deleted user group ID: " + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to delete user group ID: " + or + "RepoGroup assigned to " + } + + """ + user_group = get_user_group_or_error(usergroupid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this user group ! + _perms = ('usergroup.admin',) + if not HasUserGroupPermissionAny(*_perms)( + user=apiuser, user_group_name=user_group.users_group_name): + raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) - @HasPermissionAllDecorator('hg.admin') - def add_user_to_users_group(self, apiuser, usersgroupid, userid): - """" - Add a user to a user group + try: + UserGroupModel().delete(user_group) + Session().commit() + return dict( + msg='deleted user group ID:%s %s' % + (user_group.users_group_id, user_group.users_group_name), + user_group=None + ) + except UserGroupsAssignedException, e: + log.error(traceback.format_exc()) + raise JSONRPCError(str(e)) + except Exception: + log.error(traceback.format_exc()) + raise JSONRPCError('failed to delete user group ID:%s %s' % + (user_group.users_group_id, + user_group.users_group_name) + ) + + # permission check inside + def add_user_to_user_group(self, apiuser, usergroupid, userid): + """ + Adds a user to a user group. If user exists in that group success will be + `false`. This command can be executed only using api_key + belonging to user with admin rights or an admin of given user group - :param apiuser: - :param usersgroupid: + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param usergroupid: + :type usergroupid: int :param userid: + :type userid: int + + OUTPUT:: + + id : + result : { + "success": True|False # depends on if member is in group + "msg": "added member `` to user group `` | + User is already in that group" + + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to add member to user group ``" + } + """ user = get_user_or_error(userid) - users_group = get_users_group_or_error(usersgroupid) + user_group = get_user_group_or_error(usergroupid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this user group ! + _perms = ('usergroup.admin',) + if not HasUserGroupPermissionAny(*_perms)( + user=apiuser, user_group_name=user_group.users_group_name): + raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) try: - ugm = UserGroupModel().add_user_to_group(users_group, user) + ugm = UserGroupModel().add_user_to_group(user_group, user) success = True if ugm != True else False msg = 'added member `%s` to user group `%s`' % ( - user.username, users_group.users_group_name - ) + user.username, user_group.users_group_name + ) msg = msg if success else 'User is already in that group' Session().commit() @@ -649,28 +1136,48 @@ class ApiController(JSONRPCController): log.error(traceback.format_exc()) raise JSONRPCError( 'failed to add member to user group `%s`' % ( - users_group.users_group_name + user_group.users_group_name, ) ) - @HasPermissionAllDecorator('hg.admin') - def remove_user_from_users_group(self, apiuser, usersgroupid, userid): + # permission check inside + def remove_user_from_user_group(self, apiuser, usergroupid, userid): """ - Remove user from a group + Removes a user from a user group. If user is not in given group success will + be `false`. This command can be executed only + using api_key belonging to user with admin rights or an admin of given user group + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param usergroupid: + :param userid: + - :param apiuser: - :param usersgroupid: - :param userid: + OUTPUT:: + + id : + result: { + "success": True|False, # depends on if member is in group + "msg": "removed member from user group | + User wasn't in group" + } + error: null + """ user = get_user_or_error(userid) - users_group = get_users_group_or_error(usersgroupid) + user_group = get_user_group_or_error(usergroupid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this user group ! + _perms = ('usergroup.admin',) + if not HasUserGroupPermissionAny(*_perms)( + user=apiuser, user_group_name=user_group.users_group_name): + raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) try: - success = UserGroupModel().remove_user_from_group(users_group, - user) + success = UserGroupModel().remove_user_from_group(user_group, user) msg = 'removed member `%s` from user group `%s`' % ( - user.username, users_group.users_group_name - ) + user.username, user_group.users_group_name + ) msg = msg if success else "User wasn't in group" Session().commit() return dict(success=success, msg=msg) @@ -678,42 +1185,99 @@ class ApiController(JSONRPCController): log.error(traceback.format_exc()) raise JSONRPCError( 'failed to remove member from user group `%s`' % ( - users_group.users_group_name - ) + user_group.users_group_name, + ) ) + # permission check inside def get_repo(self, apiuser, repoid): - """" - Get repository by name + """ + Gets an existing repository by it's name or repository_id. Members will return + either users_group or user associated to that repository. This command can be + executed only using api_key belonging to user with admin + rights or regular user that have at least read access to repository. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int + + OUTPUT:: - :param apiuser: - :param repoid: + id : + result : { + { + "repo_id" : "", + "repo_name" : "" + "repo_type" : "", + "clone_uri" : "", + "enable_downloads": "", + "enable_locking": "", + "enable_statistics": "", + "private": "", + "created_on" : "", + "description" : "", + "landing_rev": "", + "last_changeset": { + "author": "", + "date": "", + "message": "", + "raw_id": "", + "revision": "", + "short_id": "" + } + "owner": "", + "fork_of": "", + "members" : [ + { + "name": "", + "type" : "user", + "permission" : "repository.(read|write|admin)" + }, + … + { + "name": "", + "type" : "user_group", + "permission" : "usergroup.(read|write|admin)" + }, + … + ] + "followers": [, ...] + ] + } + } + error : null + """ repo = get_repo_or_error(repoid) if not HasPermissionAnyApi('hg.admin')(user=apiuser): # check if we have admin permission for this repo ! - if not HasRepoPermissionAnyApi('repository.admin')(user=apiuser, - repo_name=repo.repo_name): - raise JSONRPCError('repository `%s` does not exist' % (repoid)) + perms = ('repository.admin', 'repository.write', 'repository.read') + if not HasRepoPermissionAnyApi(*perms)(user=apiuser, repo_name=repo.repo_name): + raise JSONRPCError('repository `%s` does not exist' % (repoid,)) members = [] followers = [] for user in repo.repo_to_perm: perm = user.permission.permission_name user = user.user - user_data = user.get_api_data() - user_data['type'] = "user" - user_data['permission'] = perm + user_data = { + 'name': user.username, + 'type': "user", + 'permission': perm + } members.append(user_data) - for users_group in repo.users_group_to_perm: - perm = users_group.permission.permission_name - users_group = users_group.users_group - users_group_data = users_group.get_api_data() - users_group_data['type'] = "users_group" - users_group_data['permission'] = perm - members.append(users_group_data) + for user_group in repo.users_group_to_perm: + perm = user_group.permission.permission_name + user_group = user_group.users_group + user_group_data = { + 'name': user_group.users_group_name, + 'type': "user_group", + 'permission': perm + } + members.append(user_group_data) for user in repo.followers: followers.append(user.user.get_api_data()) @@ -725,13 +1289,39 @@ class ApiController(JSONRPCController): # permission check inside def get_repos(self, apiuser): - """" - Get all repositories + """ + Lists all existing repositories. This command can be executed only using + api_key belonging to user with admin rights or regular user that have + admin, write or read access to repository. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + + OUTPUT:: - :param apiuser: + id : + result: [ + { + "repo_id" : "", + "repo_name" : "" + "repo_type" : "", + "clone_uri" : "", + "private": : "", + "created_on" : "", + "description" : "", + "landing_rev": "", + "owner": "", + "fork_of": "", + "enable_downloads": "", + "enable_locking": "", + "enable_statistics": "", + }, + … + ] + error: null """ result = [] - if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: + if not HasPermissionAnyApi('hg.admin')(user=apiuser): repos = RepoModel().get_all_user_repos(user=apiuser) else: repos = RepoModel().get_all() @@ -740,21 +1330,49 @@ class ApiController(JSONRPCController): result.append(repo.get_api_data()) return result - @HasPermissionAllDecorator('hg.admin') + # permission check inside def get_repo_nodes(self, apiuser, repoid, revision, root_path, - ret_type='all'): + ret_type=Optional('all')): """ - returns a list of nodes and it's children - for a given path at given revision. It's possible to specify ret_type - to show only files or dirs + returns a list of nodes and it's children in a flat list for a given path + at given revision. It's possible to specify ret_type to show only `files` or + `dirs`. This command can be executed only using api_key belonging to + user with admin rights or regular user that have at least read access to repository. - :param apiuser: - :param repoid: name or id of repository + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int :param revision: revision for which listing should be done + :type revision: str :param root_path: path from which start displaying + :type root_path: str :param ret_type: return type 'all|files|dirs' nodes + :type ret_type: Optional(str) + + + OUTPUT:: + + id : + result: [ + { + "name" : "" + "type" : "", + }, + … + ] + error: null """ repo = get_repo_or_error(repoid) + + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this repo ! + perms = ('repository.admin', 'repository.write', 'repository.read') + if not HasRepoPermissionAnyApi(*perms)(user=apiuser, repo_name=repo.repo_name): + raise JSONRPCError('repository `%s` does not exist' % (repoid,)) + + ret_type = Optional.extract(ret_type) + _map = {} try: _d, _f = ScmModel().get_nodes(repo, revision, root_path, flat=False) @@ -765,7 +1383,8 @@ class ApiController(JSONRPCController): } return _map[ret_type] except KeyError: - raise JSONRPCError('ret_type must be one of %s' % _map.keys()) + raise JSONRPCError('ret_type must be one of %s' + % (','.join(_map.keys()))) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( @@ -774,31 +1393,71 @@ class ApiController(JSONRPCController): @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository') def create_repo(self, apiuser, repo_name, owner=Optional(OAttr('apiuser')), - repo_type=Optional('hg'), - description=Optional(''), private=Optional(False), - clone_uri=Optional(None), landing_rev=Optional('tip'), + repo_type=Optional('hg'), description=Optional(''), + private=Optional(False), clone_uri=Optional(None), + landing_rev=Optional('rev:tip'), enable_statistics=Optional(False), enable_locking=Optional(False), - enable_downloads=Optional(False)): + enable_downloads=Optional(False), + copy_permissions=Optional(False)): """ - Create repository, if clone_url is given it makes a remote clone - if repo_name is within a group name the groups will be created - automatically if they aren't present + Creates a repository. If repository name contains "/", all needed repository + groups will be created. For example "foo/bar/baz" will create groups + "foo", "bar" (with "foo" as parent), and create "baz" repository with + "bar" as group. This command can be executed only using api_key + belonging to user with admin rights or regular user that have create + repository permission. Regular users cannot specify owner parameter - :param apiuser: - :param repo_name: - :param onwer: - :param repo_type: - :param description: + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repo_name: repository name + :type repo_name: str + :param owner: user_id or username + :type owner: Optional(str) + :param repo_type: 'hg' or 'git' + :type repo_type: Optional(str) + :param description: repository description + :type description: Optional(str) :param private: + :type private: bool :param clone_uri: - :param landing_rev: + :type clone_uri: str + :param landing_rev: : + :type landing_rev: str + :param enable_locking: + :type enable_locking: bool + :param enable_downloads: + :type enable_downloads: bool + :param enable_statistics: + :type enable_statistics: bool + :param copy_permissions: Copy permission from group that repository is + beeing created. + :type copy_permissions: bool + + OUTPUT:: + + id : + result: { + "msg": "Created new repository ``", + "success": true, + "task": "" + } + error: null + + ERROR OUTPUT:: + + id : + result : null + error : { + 'failed to create repository `` + } + """ - if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: + if not HasPermissionAnyApi('hg.admin')(user=apiuser): if not isinstance(owner, Optional): #forbid setting owner for non-admins raise JSONRPCError( - 'Only RhodeCode admin can specify `owner` param' + 'Only Kallithea admin can specify `owner` param' ) if isinstance(owner, Optional): owner = apiuser.user_id @@ -808,7 +1467,7 @@ class ApiController(JSONRPCController): if RepoModel().get_by_repo_name(repo_name): raise JSONRPCError("repo `%s` already exist" % repo_name) - defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True) + defs = Setting.get_default_repo_settings(strip_prefix=True) if isinstance(private, Optional): private = defs.get('repo_private') or Optional.extract(private) if isinstance(repo_type, Optional): @@ -823,40 +1482,51 @@ class ApiController(JSONRPCController): clone_uri = Optional.extract(clone_uri) description = Optional.extract(description) landing_rev = Optional.extract(landing_rev) + copy_permissions = Optional.extract(copy_permissions) try: + repo_name_cleaned = repo_name.split('/')[-1] # create structure of groups and return the last group - group = map_groups(repo_name) - - repo = RepoModel().create_repo( - repo_name=repo_name, + repo_group = map_groups(repo_name) + data = dict( + repo_name=repo_name_cleaned, + repo_name_full=repo_name, repo_type=repo_type, - description=description, + repo_description=description, owner=owner, - private=private, + repo_private=private, clone_uri=clone_uri, - repos_group=group, - landing_rev=landing_rev, + repo_group=repo_group, + repo_landing_rev=landing_rev, enable_statistics=enable_statistics, + enable_locking=enable_locking, enable_downloads=enable_downloads, - enable_locking=enable_locking + repo_copy_permissions=copy_permissions, ) - Session().commit() + task = RepoModel().create(form_data=data, cur_user=owner) + from celery.result import BaseAsyncResult + task_id = None + if isinstance(task, BaseAsyncResult): + task_id = task.task_id + # no commit, it's done in RepoModel, or async via celery return dict( - msg="Created new repository `%s`" % (repo.repo_name), - repo=repo.get_api_data() + msg="Created new repository `%s`" % (repo_name,), + success=True, # cannot return the repo data here since fork + # cann be done async + task=task_id ) except Exception: log.error(traceback.format_exc()) - raise JSONRPCError('failed to create repository `%s`' % repo_name) + raise JSONRPCError( + 'failed to create repository `%s`' % (repo_name,)) # permission check inside def update_repo(self, apiuser, repoid, name=Optional(None), owner=Optional(OAttr('apiuser')), group=Optional(None), description=Optional(''), private=Optional(False), - clone_uri=Optional(None), landing_rev=Optional('tip'), + clone_uri=Optional(None), landing_rev=Optional('rev:tip'), enable_statistics=Optional(False), enable_locking=Optional(False), enable_downloads=Optional(False)): @@ -917,9 +1587,53 @@ class ApiController(JSONRPCController): raise JSONRPCError('failed to update repo `%s`' % repoid) @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository') - def fork_repo(self, apiuser, repoid, fork_name, owner=Optional(OAttr('apiuser')), + def fork_repo(self, apiuser, repoid, fork_name, + owner=Optional(OAttr('apiuser')), description=Optional(''), copy_permissions=Optional(False), - private=Optional(False), landing_rev=Optional('tip')): + private=Optional(False), landing_rev=Optional('rev:tip')): + """ + Creates a fork of given repo. In case of using celery this will + immidiatelly return success message, while fork is going to be created + asynchronous. This command can be executed only using api_key belonging to + user with admin rights or regular user that have fork permission, and at least + read access to forking repository. Regular users cannot specify owner parameter. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int + :param fork_name: + :param owner: + :param description: + :param copy_permissions: + :param private: + :param landing_rev: + + INPUT:: + + id : + api_key : "" + args: { + "repoid" : "", + "fork_name": "", + "owner": "", + "description": "", + "copy_permissions": "", + "private": "", + "landing_rev": "" + } + + OUTPUT:: + + id : + result: { + "msg": "Created fork of `` as ``", + "success": true, + "task": "" + } + error: null + + """ repo = get_repo_or_error(repoid) repo_name = repo.repo_name @@ -937,10 +1651,10 @@ class ApiController(JSONRPCController): if not isinstance(owner, Optional): #forbid setting owner for non-admins raise JSONRPCError( - 'Only RhodeCode admin can specify `owner` param' + 'Only Kallithea admin can specify `owner` param' ) else: - raise JSONRPCError('repository `%s` does not exist' % (repoid)) + raise JSONRPCError('repository `%s` does not exist' % (repoid,)) if isinstance(owner, Optional): owner = apiuser.user_id @@ -963,12 +1677,18 @@ class ApiController(JSONRPCController): update_after_clone=False, fork_parent_id=repo.repo_id, ) - RepoModel().create_fork(form_data, cur_user=owner) + task = RepoModel().create_fork(form_data, cur_user=owner) + # no commit, it's done in RepoModel, or async via celery + from celery.result import BaseAsyncResult + task_id = None + if isinstance(task, BaseAsyncResult): + task_id = task.task_id return dict( msg='Created fork of `%s` as `%s`' % (repo.repo_name, fork_name), - success=True # cannot return the repo data here since fork - # cann be done async + success=True, # cannot return the repo data here since fork + # cann be done async + task=task_id ) except Exception: log.error(traceback.format_exc()) @@ -977,22 +1697,38 @@ class ApiController(JSONRPCController): fork_name) ) - # perms handled inside - def delete_repo(self, apiuser, repoid, forks=Optional(None)): + # permission check inside + def delete_repo(self, apiuser, repoid, forks=Optional('')): """ - Deletes a given repository + Deletes a repository. This command can be executed only using api_key belonging + to user with admin rights or regular user that have admin access to repository. + When `forks` param is set it's possible to detach or delete forks of deleting + repository - :param apiuser: - :param repoid: - :param forks: detach or delete, what do do with attached forks for repo + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int + :param forks: `detach` or `delete`, what do do with attached forks for repo + :type forks: Optional(str) + + OUTPUT:: + + id : + result: { + "msg": "Deleted repository ``", + "success": true + } + error: null + """ repo = get_repo_or_error(repoid) - if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: + if not HasPermissionAnyApi('hg.admin')(user=apiuser): # check if we have admin permission for this repo ! - if HasRepoPermissionAnyApi('repository.admin')(user=apiuser, - repo_name=repo.repo_name) is False: - raise JSONRPCError('repository `%s` does not exist' % (repoid)) + if not HasRepoPermissionAnyApi('repository.admin')(user=apiuser, + repo_name=repo.repo_name): + raise JSONRPCError('repository `%s` does not exist' % (repoid,)) try: handle_forks = Optional.extract(forks) @@ -1004,8 +1740,8 @@ class ApiController(JSONRPCController): _forks_msg = ' ' + 'Deleted %s forks' % len(_forks) elif _forks: raise JSONRPCError( - 'Cannot delete `%s` it still contains attached forks' - % repo.repo_name + 'Cannot delete `%s` it still contains attached forks' % + (repo.repo_name,) ) RepoModel().delete(repo, forks=forks) @@ -1017,18 +1753,32 @@ class ApiController(JSONRPCController): except Exception: log.error(traceback.format_exc()) raise JSONRPCError( - 'failed to delete repository `%s`' % repo.repo_name + 'failed to delete repository `%s`' % (repo.repo_name,) ) @HasPermissionAllDecorator('hg.admin') def grant_user_permission(self, apiuser, repoid, userid, perm): """ Grant permission for user on given repository, or update existing one - if found + if found. This command can be executed only using api_key belonging to user + with admin rights. - :param repoid: + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int :param userid: - :param perm: + :param perm: (repository.(none|read|write|admin)) + :type perm: str + + OUTPUT:: + + id : + result: { + "msg" : "Granted perm: `` for user: `` in repo: ``", + "success": true + } + error: null """ repo = get_repo_or_error(repoid) user = get_user_or_error(userid) @@ -1056,19 +1806,30 @@ class ApiController(JSONRPCController): @HasPermissionAllDecorator('hg.admin') def revoke_user_permission(self, apiuser, repoid, userid): """ - Revoke permission for user on given repository + Revoke permission for user on given repository. This command can be executed + only using api_key belonging to user with admin rights. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int + :param userid: - :param apiuser: - :param repoid: - :param userid: + OUTPUT:: + + id : + result: { + "msg" : "Revoked perm for user: `` in repo: ``", + "success": true + } + error: null + """ repo = get_repo_or_error(repoid) user = get_user_or_error(userid) try: - RepoModel().revoke_user_permission(repo=repo, user=user) - Session().commit() return dict( msg='Revoked perm for user: `%s` in repo: `%s`' % ( @@ -1084,33 +1845,123 @@ class ApiController(JSONRPCController): ) ) - @HasPermissionAllDecorator('hg.admin') - def grant_users_group_permission(self, apiuser, repoid, usersgroupid, - perm): + # permission check inside + def grant_user_group_permission(self, apiuser, repoid, usergroupid, perm): """ Grant permission for user group on given repository, or update - existing one if found + existing one if found. This command can be executed only using + api_key belonging to user with admin rights. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int + :param usergroupid: id of usergroup + :type usergroupid: str or int + :param perm: (repository.(none|read|write|admin)) + :type perm: str + + OUTPUT:: - :param apiuser: - :param repoid: - :param usersgroupid: - :param perm: + id : + result : { + "msg" : "Granted perm: `` for group: `` in repo: ``", + "success": true + + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to edit permission for user group: `` in repo ``' + } + """ repo = get_repo_or_error(repoid) perm = get_perm_or_error(perm) - users_group = get_users_group_or_error(usersgroupid) + user_group = get_user_group_or_error(usergroupid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this repo ! + _perms = ('repository.admin',) + if not HasRepoPermissionAnyApi(*_perms)( + user=apiuser, repo_name=repo.repo_name): + raise JSONRPCError('repository `%s` does not exist' % (repoid,)) + + # check if we have at least read permission for this user group ! + _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) + if not HasUserGroupPermissionAny(*_perms)( + user=apiuser, user_group_name=user_group.users_group_name): + raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) try: - RepoModel().grant_users_group_permission(repo=repo, - group_name=users_group, - perm=perm) + RepoModel().grant_user_group_permission( + repo=repo, group_name=user_group, perm=perm) Session().commit() return dict( msg='Granted perm: `%s` for user group: `%s` in ' 'repo: `%s`' % ( - perm.permission_name, users_group.users_group_name, - repo.repo_name + perm.permission_name, user_group.users_group_name, + repo.repo_name + ), + success=True + ) + except Exception: + log.error(traceback.format_exc()) + raise JSONRPCError( + 'failed to edit permission for user group: `%s` in ' + 'repo: `%s`' % ( + usergroupid, repo.repo_name + ) + ) + + # permission check inside + def revoke_user_group_permission(self, apiuser, repoid, usergroupid): + """ + Revoke permission for user group on given repository. This command can be + executed only using api_key belonging to user with admin rights. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repoid: repository name or repository id + :type repoid: str or int + :param usergroupid: + + OUTPUT:: + + id : + result: { + "msg" : "Revoked perm for group: `` in repo: ``", + "success": true + } + error: null + """ + repo = get_repo_or_error(repoid) + user_group = get_user_group_or_error(usergroupid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this repo ! + _perms = ('repository.admin',) + if not HasRepoPermissionAnyApi(*_perms)( + user=apiuser, repo_name=repo.repo_name): + raise JSONRPCError('repository `%s` does not exist' % (repoid,)) + + # check if we have at least read permission for this user group ! + _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) + if not HasUserGroupPermissionAny(*_perms)( + user=apiuser, user_group_name=user_group.users_group_name): + raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) + + try: + RepoModel().revoke_user_group_permission( + repo=repo, group_name=user_group) + + Session().commit() + return dict( + msg='Revoked perm for user group: `%s` in repo: `%s`' % ( + user_group.users_group_name, repo.repo_name ), success=True ) @@ -1119,46 +1970,579 @@ class ApiController(JSONRPCController): raise JSONRPCError( 'failed to edit permission for user group: `%s` in ' 'repo: `%s`' % ( - usersgroupid, repo.repo_name + user_group.users_group_name, repo.repo_name ) ) @HasPermissionAllDecorator('hg.admin') - def revoke_users_group_permission(self, apiuser, repoid, usersgroupid): + def get_repo_group(self, apiuser, repogroupid): + """ + Returns given repo group together with permissions, and repositories + inside the group + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repogroupid: id/name of repository group + :type repogroupid: str or int + """ + repo_group = get_repo_group_or_error(repogroupid) + + members = [] + for user in repo_group.repo_group_to_perm: + perm = user.permission.permission_name + user = user.user + user_data = { + 'name': user.username, + 'type': "user", + 'permission': perm + } + members.append(user_data) + + for user_group in repo_group.users_group_to_perm: + perm = user_group.permission.permission_name + user_group = user_group.users_group + user_group_data = { + 'name': user_group.users_group_name, + 'type': "user_group", + 'permission': perm + } + members.append(user_group_data) + + data = repo_group.get_api_data() + data["members"] = members + return data + + @HasPermissionAllDecorator('hg.admin') + def get_repo_groups(self, apiuser): """ - Revoke permission for user group on given repository + Returns all repository groups + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + """ + result = [] + for repo_group in RepoGroupModel().get_all(): + result.append(repo_group.get_api_data()) + return result + + @HasPermissionAllDecorator('hg.admin') + def create_repo_group(self, apiuser, group_name, description=Optional(''), + owner=Optional(OAttr('apiuser')), + parent=Optional(None), + copy_permissions=Optional(False)): + """ + Creates a repository group. This command can be executed only using + api_key belonging to user with admin rights. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param group_name: + :type group_name: + :param description: + :type description: + :param owner: + :type owner: + :param parent: + :type parent: + :param copy_permissions: + :type copy_permissions: + + OUTPUT:: + + id : + result : { + "msg": "created new repo group ``" + "repo_group": + } + error : null + + ERROR OUTPUT:: - :param apiuser: - :param repoid: - :param usersgroupid: + id : + result : null + error : { + failed to create repo group `` + } + """ - repo = get_repo_or_error(repoid) - users_group = get_users_group_or_error(usersgroupid) + if RepoGroup.get_by_group_name(group_name): + raise JSONRPCError("repo group `%s` already exist" % (group_name,)) + + if isinstance(owner, Optional): + owner = apiuser.user_id + group_description = Optional.extract(description) + parent_group = Optional.extract(parent) + if not isinstance(parent, Optional): + parent_group = get_repo_group_or_error(parent_group) + + copy_permissions = Optional.extract(copy_permissions) + try: + repo_group = RepoGroupModel().create( + group_name=group_name, + group_description=group_description, + owner=owner, + parent=parent_group, + copy_permissions=copy_permissions + ) + Session().commit() + return dict( + msg='created new repo group `%s`' % group_name, + repo_group=repo_group.get_api_data() + ) + except Exception: + + log.error(traceback.format_exc()) + raise JSONRPCError('failed to create repo group `%s`' % (group_name,)) + + @HasPermissionAllDecorator('hg.admin') + def update_repo_group(self, apiuser, repogroupid, group_name=Optional(''), + description=Optional(''), + owner=Optional(OAttr('apiuser')), + parent=Optional(None), enable_locking=Optional(False)): + repo_group = get_repo_group_or_error(repogroupid) + + updates = {} + try: + store_update(updates, group_name, 'group_name') + store_update(updates, description, 'group_description') + store_update(updates, owner, 'owner') + store_update(updates, parent, 'parent_group') + store_update(updates, enable_locking, 'enable_locking') + repo_group = RepoGroupModel().update(repo_group, updates) + Session().commit() + return dict( + msg='updated repository group ID:%s %s' % (repo_group.group_id, + repo_group.group_name), + repo_group=repo_group.get_api_data() + ) + except Exception: + log.error(traceback.format_exc()) + raise JSONRPCError('failed to update repository group `%s`' + % (repogroupid,)) + + @HasPermissionAllDecorator('hg.admin') + def delete_repo_group(self, apiuser, repogroupid): + """ + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repogroupid: name or id of repository group + :type repogroupid: str or int + + OUTPUT:: + + id : + result : { + 'msg': 'deleted repo group ID: + 'repo_group': null + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to delete repo group ID: " + } + + """ + repo_group = get_repo_group_or_error(repogroupid) try: - RepoModel().revoke_users_group_permission(repo=repo, - group_name=users_group) - + RepoGroupModel().delete(repo_group) Session().commit() return dict( - msg='Revoked perm for user group: `%s` in repo: `%s`' % ( - users_group.users_group_name, repo.repo_name + msg='deleted repo group ID:%s %s' % + (repo_group.group_id, repo_group.group_name), + repo_group=None + ) + except Exception: + log.error(traceback.format_exc()) + raise JSONRPCError('failed to delete repo group ID:%s %s' % + (repo_group.group_id, repo_group.group_name) + ) + + # permission check inside + def grant_user_permission_to_repo_group(self, apiuser, repogroupid, userid, + perm, apply_to_children=Optional('none')): + """ + Grant permission for user on given repository group, or update existing + one if found. This command can be executed only using api_key belonging + to user with admin rights, or user who has admin right to given repository + group. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repogroupid: name or id of repository group + :type repogroupid: str or int + :param userid: + :param perm: (group.(none|read|write|admin)) + :type perm: str + :param apply_to_children: 'none', 'repos', 'groups', 'all' + :type apply_to_children: str + + OUTPUT:: + + id : + result: { + "msg" : "Granted perm: `` (recursive:) for user: `` in repo group: ``", + "success": true + } + error: null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to edit permission for user: `` in repo group: ``" + } + + """ + + repo_group = get_repo_group_or_error(repogroupid) + + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this repo group ! + if not HasRepoGroupPermissionAnyApi('group.admin')(user=apiuser, + group_name=repo_group.group_name): + raise JSONRPCError('repository group `%s` does not exist' % (repogroupid,)) + + user = get_user_or_error(userid) + perm = get_perm_or_error(perm, prefix='group.') + apply_to_children = Optional.extract(apply_to_children) + + try: + RepoGroupModel().add_permission(repo_group=repo_group, + obj=user, + obj_type="user", + perm=perm, + recursive=apply_to_children) + Session().commit() + return dict( + msg='Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % ( + perm.permission_name, apply_to_children, user.username, repo_group.name ), success=True ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( + 'failed to edit permission for user: `%s` in repo group: `%s`' % ( + userid, repo_group.name)) + + # permission check inside + def revoke_user_permission_from_repo_group(self, apiuser, repogroupid, userid, + apply_to_children=Optional('none')): + """ + Revoke permission for user on given repository group. This command can + be executed only using api_key belonging to user with admin rights, or + user who has admin right to given repository group. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repogroupid: name or id of repository group + :type repogroupid: str or int + :param userid: + :type userid: + :param apply_to_children: 'none', 'repos', 'groups', 'all' + :type apply_to_children: str + + OUTPUT:: + + id : + result: { + "msg" : "Revoked perm (recursive:) for user: `` in repo group: ``", + "success": true + } + error: null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to edit permission for user: `` in repo group: ``" + } + + """ + + repo_group = get_repo_group_or_error(repogroupid) + + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this repo group ! + if not HasRepoGroupPermissionAnyApi('group.admin')(user=apiuser, + group_name=repo_group.group_name): + raise JSONRPCError('repository group `%s` does not exist' % (repogroupid,)) + + user = get_user_or_error(userid) + apply_to_children = Optional.extract(apply_to_children) + + try: + RepoGroupModel().delete_permission(repo_group=repo_group, + obj=user, + obj_type="user", + recursive=apply_to_children) + + Session().commit() + return dict( + msg='Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % ( + apply_to_children, user.username, repo_group.name + ), + success=True + ) + except Exception: + log.error(traceback.format_exc()) + raise JSONRPCError( + 'failed to edit permission for user: `%s` in repo group: `%s`' % ( + userid, repo_group.name)) + + # permission check inside + def grant_user_group_permission_to_repo_group( + self, apiuser, repogroupid, usergroupid, perm, + apply_to_children=Optional('none'),): + """ + Grant permission for user group on given repository group, or update + existing one if found. This command can be executed only using + api_key belonging to user with admin rights, or user who has admin + right to given repository group. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repogroupid: name or id of repository group + :type repogroupid: str or int + :param usergroupid: id of usergroup + :type usergroupid: str or int + :param perm: (group.(none|read|write|admin)) + :type perm: str + :param apply_to_children: 'none', 'repos', 'groups', 'all' + :type apply_to_children: str + + OUTPUT:: + + id : + result : { + "msg" : "Granted perm: `` (recursive:) for user group: `` in repo group: ``", + "success": true + + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to edit permission for user group: `` in repo group: ``" + } + + """ + repo_group = get_repo_group_or_error(repogroupid) + perm = get_perm_or_error(perm, prefix='group.') + user_group = get_user_group_or_error(usergroupid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this repo group ! + _perms = ('group.admin',) + if not HasRepoGroupPermissionAnyApi(*_perms)( + user=apiuser, group_name=repo_group.group_name): + raise JSONRPCError( + 'repository group `%s` does not exist' % (repogroupid,)) + + # check if we have at least read permission for this user group ! + _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) + if not HasUserGroupPermissionAny(*_perms)( + user=apiuser, user_group_name=user_group.users_group_name): + raise JSONRPCError( + 'user group `%s` does not exist' % (usergroupid,)) + + apply_to_children = Optional.extract(apply_to_children) + + try: + RepoGroupModel().add_permission(repo_group=repo_group, + obj=user_group, + obj_type="user_group", + perm=perm, + recursive=apply_to_children) + Session().commit() + return dict( + msg='Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % ( + perm.permission_name, apply_to_children, + user_group.users_group_name, repo_group.name + ), + success=True + ) + except Exception: + log.error(traceback.format_exc()) + raise JSONRPCError( 'failed to edit permission for user group: `%s` in ' - 'repo: `%s`' % ( - users_group.users_group_name, repo.repo_name + 'repo group: `%s`' % ( + usergroupid, repo_group.name ) ) + # permission check inside + def revoke_user_group_permission_from_repo_group( + self, apiuser, repogroupid, usergroupid, + apply_to_children=Optional('none')): + """ + Revoke permission for user group on given repository. This command can be + executed only using api_key belonging to user with admin rights, or + user who has admin right to given repository group. + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param repogroupid: name or id of repository group + :type repogroupid: str or int + :param usergroupid: + :param apply_to_children: 'none', 'repos', 'groups', 'all' + :type apply_to_children: str + + OUTPUT:: + + id : + result: { + "msg" : "Revoked perm (recursive:) for user group: `` in repo group: ``", + "success": true + } + error: null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to edit permission for user group: `` in repo group: ``" + } + + + """ + repo_group = get_repo_group_or_error(repogroupid) + user_group = get_user_group_or_error(usergroupid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # check if we have admin permission for this repo group ! + _perms = ('group.admin',) + if not HasRepoGroupPermissionAnyApi(*_perms)( + user=apiuser, group_name=repo_group.group_name): + raise JSONRPCError( + 'repository group `%s` does not exist' % (repogroupid,)) + + # check if we have at least read permission for this user group ! + _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) + if not HasUserGroupPermissionAny(*_perms)( + user=apiuser, user_group_name=user_group.users_group_name): + raise JSONRPCError( + 'user group `%s` does not exist' % (usergroupid,)) + + apply_to_children = Optional.extract(apply_to_children) + + try: + RepoGroupModel().delete_permission(repo_group=repo_group, + obj=user_group, + obj_type="user_group", + recursive=apply_to_children) + Session().commit() + return dict( + msg='Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % ( + apply_to_children, user_group.users_group_name, repo_group.name + ), + success=True + ) + except Exception: + log.error(traceback.format_exc()) + raise JSONRPCError( + 'failed to edit permission for user group: `%s` in repo group: `%s`' % ( + user_group.users_group_name, repo_group.name + ) + ) + + def get_gist(self, apiuser, gistid): + """ + Get given gist by id + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param gistid: id of private or public gist + :type gistid: str + """ + gist = get_gist_or_error(gistid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + if gist.gist_owner != apiuser.user_id: + raise JSONRPCError('gist `%s` does not exist' % (gistid,)) + return gist.get_api_data() + + def get_gists(self, apiuser, userid=Optional(OAttr('apiuser'))): + """ + Get all gists for given user. If userid is empty returned gists + are for user who called the api + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param userid: user to get gists for + :type userid: Optional(str or int) + """ + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + # make sure normal user does not pass someone else userid, + # he is not allowed to do that + if not isinstance(userid, Optional) and userid != apiuser.user_id: + raise JSONRPCError( + 'userid is not the same as your user' + ) + + if isinstance(userid, Optional): + user_id = apiuser.user_id + else: + user_id = get_user_or_error(userid).user_id + + gists = [] + _gists = Gist().query()\ + .filter(or_(Gist.gist_expires == -1, Gist.gist_expires >= time.time()))\ + .filter(Gist.gist_owner == user_id)\ + .order_by(Gist.created_on.desc()) + for gist in _gists: + gists.append(gist.get_api_data()) + return gists + def create_gist(self, apiuser, files, owner=Optional(OAttr('apiuser')), gist_type=Optional(Gist.GIST_PUBLIC), lifetime=Optional(-1), description=Optional('')): + """ + Creates new Gist + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param files: files to be added to gist + {'filename': {'content':'...', 'lexer': null}, + 'filename2': {'content':'...', 'lexer': null}} + :type files: dict + :param owner: gist owner, defaults to api method caller + :type owner: Optional(str or int) + :param gist_type: type of gist 'public' or 'private' + :type gist_type: Optional(str) + :param lifetime: time in minutes of gist lifetime + :type lifetime: Optional(int) + :param description: gist description + :type description: Optional(str) + + OUTPUT:: + + id : + result : { + "msg": "created new gist", + "gist": {} + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to create gist" + } + + """ try: if isinstance(owner, Optional): owner = apiuser.user_id @@ -1168,10 +2552,6 @@ class ApiController(JSONRPCController): gist_type = Optional.extract(gist_type) lifetime = Optional.extract(lifetime) - # files: { - # 'filename': {'content':'...', 'lexer': null}, - # 'filename2': {'content':'...', 'lexer': null} - #} gist = GistModel().create(description=description, owner=owner, gist_mapping=files, @@ -1185,3 +2565,54 @@ class ApiController(JSONRPCController): except Exception: log.error(traceback.format_exc()) raise JSONRPCError('failed to create gist') + + # def update_gist(self, apiuser, gistid, files, owner=Optional(OAttr('apiuser')), + # gist_type=Optional(Gist.GIST_PUBLIC), + # gist_lifetime=Optional(-1), gist_description=Optional('')): + # gist = get_gist_or_error(gistid) + # updates = {} + + # permission check inside + def delete_gist(self, apiuser, gistid): + """ + Deletes existing gist + + :param apiuser: filled automatically from apikey + :type apiuser: AuthUser + :param gistid: id of gist to delete + :type gistid: str + + OUTPUT:: + + id : + result : { + "deleted gist ID: ", + "gist": null + } + error : null + + ERROR OUTPUT:: + + id : + result : null + error : { + "failed to delete gist ID:" + } + + """ + gist = get_gist_or_error(gistid) + if not HasPermissionAnyApi('hg.admin')(user=apiuser): + if gist.gist_owner != apiuser.user_id: + raise JSONRPCError('gist `%s` does not exist' % (gistid,)) + + try: + GistModel().delete(gist) + Session().commit() + return dict( + msg='deleted gist ID:%s' % (gist.gist_access_id,), + gist=None + ) + except Exception: + log.error(traceback.format_exc()) + raise JSONRPCError('failed to delete gist ID:%s' + % (gist.gist_access_id,)) diff --git a/rhodecode/controllers/bookmarks.py b/kallithea/controllers/bookmarks.py rename from rhodecode/controllers/bookmarks.py rename to kallithea/controllers/bookmarks.py --- a/rhodecode/controllers/bookmarks.py +++ b/kallithea/controllers/bookmarks.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.bookmarks - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Bookmarks controller for rhodecode - - :created_on: Dec 1, 2011 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,13 +11,27 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.bookmarks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Bookmarks controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Dec 1, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging from pylons import tmpl_context as c -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.compat import OrderedDict +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.compat import OrderedDict from webob.exc import HTTPNotFound log = logging.getLogger(__name__) @@ -43,13 +46,13 @@ class BookmarksController(BaseRepoContro @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') def index(self): - if c.rhodecode_repo.alias != 'hg': + if c.db_repo_scm_instance.alias != 'hg': raise HTTPNotFound() c.repo_bookmarks = OrderedDict() - bookmarks = [(name, c.rhodecode_repo.get_changeset(hash_)) for \ - name, hash_ in c.rhodecode_repo._repo._bookmarks.items()] + bookmarks = [(name, c.db_repo_scm_instance.get_changeset(hash_)) for \ + name, hash_ in c.db_repo_scm_instance._repo._bookmarks.items()] ordered_tags = sorted(bookmarks, key=lambda x: x[1].date, reverse=True) for name, cs_book in ordered_tags: c.repo_bookmarks[name] = cs_book diff --git a/rhodecode/controllers/branches.py b/kallithea/controllers/branches.py rename from rhodecode/controllers/branches.py rename to kallithea/controllers/branches.py --- a/rhodecode/controllers/branches.py +++ b/kallithea/controllers/branches.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.branches - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - branches controller for rhodecode - - :created_on: Apr 21, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,16 +11,29 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.branches +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +branches controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 21, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import logging import binascii from pylons import tmpl_context as c -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.compat import OrderedDict -from rhodecode.lib.utils2 import safe_unicode +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.compat import OrderedDict +from kallithea.lib.utils2 import safe_unicode log = logging.getLogger(__name__) @@ -54,11 +56,11 @@ class BranchesController(BaseRepoControl bt_closed[bn] = tip return bt_closed - cs_g = c.rhodecode_repo.get_changeset + cs_g = c.db_repo_scm_instance.get_changeset c.repo_closed_branches = {} - if c.rhodecode_db_repo.repo_type == 'hg': - bt_closed = _branchtags(c.rhodecode_repo._repo) + if c.db_repo.repo_type == 'hg': + bt_closed = _branchtags(c.db_repo_scm_instance._repo) _closed_branches = [(safe_unicode(n), cs_g(binascii.hexlify(h)),) for n, h in bt_closed.items()] @@ -67,7 +69,7 @@ class BranchesController(BaseRepoControl reverse=False)) _branches = [(safe_unicode(n), cs_g(h)) - for n, h in c.rhodecode_repo.branches.items()] + for n, h in c.db_repo_scm_instance.branches.items()] c.repo_branches = OrderedDict(sorted(_branches, key=lambda ctx: ctx[0], reverse=False)) diff --git a/rhodecode/controllers/changelog.py b/kallithea/controllers/changelog.py rename from rhodecode/controllers/changelog.py rename to kallithea/controllers/changelog.py --- a/rhodecode/controllers/changelog.py +++ b/kallithea/controllers/changelog.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.changelog - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - changelog controller for rhodecode - - :created_on: Apr 21, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.changelog +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +changelog controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 21, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import logging import traceback @@ -31,15 +33,15 @@ from pylons.controllers.util import redi from pylons.i18n.translation import _ from webob.exc import HTTPNotFound, HTTPBadRequest -import rhodecode.lib.helpers as h -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.helpers import RepoPage -from rhodecode.lib.compat import json -from rhodecode.lib.graphmod import _colored, _dagwalker -from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError,\ +import kallithea.lib.helpers as h +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.helpers import RepoPage +from kallithea.lib.compat import json +from kallithea.lib.graphmod import _colored, _dagwalker +from kallithea.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError,\ ChangesetError, NodeDoesNotExistError, EmptyRepositoryError -from rhodecode.lib.utils2 import safe_int, safe_str +from kallithea.lib.utils2 import safe_int, safe_str log = logging.getLogger(__name__) @@ -51,16 +53,16 @@ def _load_changelog_summary(): def url_generator(**kw): return url('changelog_summary_home', - repo_name=c.rhodecode_db_repo.repo_name, size=size, **kw) + repo_name=c.db_repo.repo_name, size=size, **kw) - collection = c.rhodecode_repo + collection = c.db_repo_scm_instance c.repo_changesets = RepoPage(collection, page=p, items_per_page=size, url=url_generator) page_revisions = [x.raw_id for x in list(c.repo_changesets)] - c.comments = c.rhodecode_db_repo.get_comments(page_revisions) - c.statuses = c.rhodecode_db_repo.statuses(page_revisions) + c.comments = c.db_repo.get_comments(page_revisions) + c.statuses = c.db_repo.statuses(page_revisions) class ChangelogController(BaseRepoController): @@ -81,7 +83,7 @@ class ChangelogController(BaseRepoContro """ try: - return c.rhodecode_repo.get_changeset(rev) + return c.db_repo_scm_instance.get_changeset(rev) except EmptyRepositoryError, e: if not redirect_after: return None @@ -137,8 +139,8 @@ class ChangelogController(BaseRepoContro p = safe_int(request.GET.get('page', 1), 1) branch_name = request.GET.get('branch', None) if (branch_name and - branch_name not in c.rhodecode_repo.branches and - branch_name not in c.rhodecode_repo.closed_branches and + branch_name not in c.db_repo_scm_instance.branches and + branch_name not in c.db_repo_scm_instance.closed_branches and not revision): return redirect(url('changelog_file_home', repo_name=c.repo_name, revision=branch_name, f_path=f_path or '')) @@ -149,7 +151,7 @@ class ChangelogController(BaseRepoContro if f_path: log.debug('generating changelog for path %s' % f_path) # get the history for the file ! - tip_cs = c.rhodecode_repo.get_changeset() + tip_cs = c.db_repo_scm_instance.get_changeset() try: collection = tip_cs.get_file_history(f_path) except (NodeDoesNotExistError, ChangesetError): @@ -162,7 +164,7 @@ class ChangelogController(BaseRepoContro redirect(h.url('changelog_home', repo_name=repo_name)) collection = list(reversed(collection)) else: - collection = c.rhodecode_repo.get_changesets(start=0, + collection = c.db_repo_scm_instance.get_changesets(start=0, branch_name=branch_name) c.total_cs = len(collection) @@ -170,8 +172,8 @@ class ChangelogController(BaseRepoContro items_per_page=c.size, branch=branch_name,) collection = list(c.pagination) page_revisions = [x.raw_id for x in c.pagination] - c.comments = c.rhodecode_db_repo.get_comments(page_revisions) - c.statuses = c.rhodecode_db_repo.statuses(page_revisions) + c.comments = c.db_repo.get_comments(page_revisions) + c.statuses = c.db_repo.statuses(page_revisions) except (EmptyRepositoryError), e: h.flash(safe_str(e), category='warning') return redirect(url('summary_home', repo_name=c.repo_name)) @@ -182,15 +184,15 @@ class ChangelogController(BaseRepoContro c.branch_name = branch_name c.branch_filters = [('', _('All Branches'))] + \ - [(k, k) for k in c.rhodecode_repo.branches.keys()] - if c.rhodecode_repo.closed_branches: + [(k, k) for k in c.db_repo_scm_instance.branches.keys()] + if c.db_repo_scm_instance.closed_branches: prefix = _('(closed)') + ' ' c.branch_filters += [('-', '-')] + \ - [(k, prefix + k) for k in c.rhodecode_repo.closed_branches.keys()] + [(k, prefix + k) for k in c.db_repo_scm_instance.closed_branches.keys()] _revs = [] if not f_path: _revs = [x.revision for x in c.pagination] - self._graph(c.rhodecode_repo, _revs, c.total_cs, c.size, p) + self._graph(c.db_repo_scm_instance, _revs, c.total_cs, c.size, p) return render('changelog/changelog.html') @@ -199,7 +201,7 @@ class ChangelogController(BaseRepoContro 'repository.admin') def changelog_details(self, cs): if request.environ.get('HTTP_X_PARTIAL_XHR'): - c.cs = c.rhodecode_repo.get_changeset(cs) + c.cs = c.db_repo_scm_instance.get_changeset(cs) return render('changelog/changelog_details.html') raise HTTPNotFound() diff --git a/rhodecode/controllers/changeset.py b/kallithea/controllers/changeset.py rename from rhodecode/controllers/changeset.py rename to kallithea/controllers/changeset.py --- a/rhodecode/controllers/changeset.py +++ b/kallithea/controllers/changeset.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.changeset - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - changeset controller for pylons showoing changes beetween - revisions - - :created_on: Apr 25, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,6 +11,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.changeset +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +changeset controller for pylons showoing changes beetween +revisions + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 25, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import traceback from collections import defaultdict @@ -31,27 +34,27 @@ from webob.exc import HTTPForbidden, HTT from pylons import tmpl_context as c, url, request, response from pylons.i18n.translation import _ from pylons.controllers.util import redirect -from rhodecode.lib.utils import jsonify +from kallithea.lib.utils import jsonify -from rhodecode.lib.vcs.exceptions import RepositoryError, \ +from kallithea.lib.vcs.exceptions import RepositoryError, \ ChangesetDoesNotExistError -import rhodecode.lib.helpers as h -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\ +import kallithea.lib.helpers as h +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\ NotAnonymous -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.utils import action_logger -from rhodecode.lib.compat import OrderedDict -from rhodecode.lib import diffs -from rhodecode.model.db import ChangesetComment, ChangesetStatus -from rhodecode.model.comment import ChangesetCommentsModel -from rhodecode.model.changeset_status import ChangesetStatusModel -from rhodecode.model.meta import Session -from rhodecode.model.repo import RepoModel -from rhodecode.lib.diffs import LimitedDiffContainer -from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError -from rhodecode.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.utils2 import safe_unicode, safe_str +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.utils import action_logger +from kallithea.lib.compat import OrderedDict +from kallithea.lib import diffs +from kallithea.model.db import ChangesetComment, ChangesetStatus +from kallithea.model.comment import ChangesetCommentsModel +from kallithea.model.changeset_status import ChangesetStatusModel +from kallithea.model.meta import Session +from kallithea.model.repo import RepoModel +from kallithea.lib.diffs import LimitedDiffContainer +from kallithea.lib.exceptions import StatusChangeOnClosedPullRequestError +from kallithea.lib.vcs.backends.base import EmptyChangeset +from kallithea.lib.utils2 import safe_unicode, safe_str log = logging.getLogger(__name__) @@ -161,7 +164,7 @@ def _context_url(GET, fileid=None): if ig_ws: params[ig_ws_key] += [ig_ws_val] - lbl = _('%s line context') % ln_ctx + lbl = _('increase diff context to %(num)s lines') % {'num': ln_ctx} params['anchor'] = fileid img = h.image(h.url('/images/icons/table_add.png'), lbl, class_='icon') @@ -173,9 +176,11 @@ class ChangesetController(BaseRepoContro def __before__(self): super(ChangesetController, self).__before__() c.affected_files_cut_off = 60 + + def __load_data(self): repo_model = RepoModel() c.users_array = repo_model.get_users_js() - c.users_groups_array = repo_model.get_users_groups_js() + c.user_groups_array = repo_model.get_user_groups_js() def _index(self, revision, method): c.anchor_url = anchor_url @@ -190,18 +195,22 @@ class ChangesetController(BaseRepoContro enable_comments = False rev_start = rev_range[0] rev_end = rev_range[1] - rev_ranges = c.rhodecode_repo.get_changesets(start=rev_start, + rev_ranges = c.db_repo_scm_instance.get_changesets(start=rev_start, end=rev_end) else: - rev_ranges = [c.rhodecode_repo.get_changeset(revision)] + rev_ranges = [c.db_repo_scm_instance.get_changeset(revision)] c.cs_ranges = list(rev_ranges) if not c.cs_ranges: raise RepositoryError('Changeset range returned empty result') - except (RepositoryError, ChangesetDoesNotExistError, Exception), e: + except(ChangesetDoesNotExistError,), e: log.error(traceback.format_exc()) - h.flash(safe_str(e), category='error') + msg = _('Such revision does not exist for this repository') + h.flash(msg, category='error') + raise HTTPNotFound() + except (Exception,), e: + log.error(traceback.format_exc()) raise HTTPNotFound() c.changes = OrderedDict() @@ -220,15 +229,15 @@ class ChangesetController(BaseRepoContro inlines = [] if method == 'show': c.statuses.extend([ChangesetStatusModel().get_status( - c.rhodecode_db_repo.repo_id, changeset.raw_id)]) + c.db_repo.repo_id, changeset.raw_id)]) c.comments.extend(ChangesetCommentsModel()\ - .get_comments(c.rhodecode_db_repo.repo_id, + .get_comments(c.db_repo.repo_id, revision=changeset.raw_id)) #comments from PR st = ChangesetStatusModel().get_statuses( - c.rhodecode_db_repo.repo_id, changeset.raw_id, + c.db_repo.repo_id, changeset.raw_id, with_revisions=True) # from associated statuses, check the pull requests, and # show comments from them @@ -239,7 +248,7 @@ class ChangesetController(BaseRepoContro for pr in prs: c.comments.extend(pr.comments) inlines = ChangesetCommentsModel()\ - .get_inline_comments(c.rhodecode_db_repo.repo_id, + .get_inline_comments(c.db_repo.repo_id, revision=changeset.raw_id) c.inline_comments.extend(inlines) @@ -250,11 +259,11 @@ class ChangesetController(BaseRepoContro context_lcl = get_line_ctx('', request.GET) ign_whitespace_lcl = ign_whitespace_lcl = get_ignore_ws('', request.GET) - _diff = c.rhodecode_repo.get_diff(cs1, cs2, + _diff = c.db_repo_scm_instance.get_diff(cs1, cs2, ignore_whitespace=ign_whitespace_lcl, context=context_lcl) diff_limit = self.cut_off_limit if not fulldiff else None diff_processor = diffs.DiffProcessor(_diff, - vcs=c.rhodecode_repo.alias, + vcs=c.db_repo_scm_instance.alias, format='gitdiff', diff_limit=diff_limit) cs_changes = OrderedDict() @@ -303,6 +312,7 @@ class ChangesetController(BaseRepoContro response.content_type = 'text/plain' return diff elif method == 'show': + self.__load_data() if len(c.cs_ranges) == 1: return render('changeset/changeset.html') else: @@ -347,8 +357,8 @@ class ChangesetController(BaseRepoContro c.co = comm = ChangesetCommentsModel().create( text=text, - repo=c.rhodecode_db_repo.repo_id, - user=c.rhodecode_user.user_id, + repo=c.db_repo.repo_id, + user=c.authuser.user_id, revision=revision, f_path=request.POST.get('f_path'), line_no=request.POST.get('line'), @@ -364,9 +374,9 @@ class ChangesetController(BaseRepoContro try: ChangesetStatusModel().set_status( - c.rhodecode_db_repo.repo_id, + c.db_repo.repo_id, status, - c.rhodecode_user.user_id, + c.authuser.user_id, comm, revision=revision, dont_allow_on_closed_pull_request=True @@ -378,9 +388,9 @@ class ChangesetController(BaseRepoContro h.flash(msg, category='warning') return redirect(h.url('changeset_home', repo_name=repo_name, revision=revision)) - action_logger(self.rhodecode_user, + action_logger(self.authuser, 'user_commented_revision:%s' % revision, - c.rhodecode_db_repo, self.ip_addr, self.sa) + c.db_repo, self.ip_addr, self.sa) Session().commit() @@ -417,8 +427,9 @@ class ChangesetController(BaseRepoContro @jsonify def delete_comment(self, repo_name, comment_id): co = ChangesetComment.get(comment_id) - owner = co.author.user_id == c.rhodecode_user.user_id - if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner: + owner = co.author.user_id == c.authuser.user_id + repo_admin = h.HasRepoPermissionAny('repository.admin') + if h.HasPermissionAny('hg.admin')() or repo_admin or owner: ChangesetCommentsModel().delete(comment=co) Session().commit() return True @@ -432,8 +443,36 @@ class ChangesetController(BaseRepoContro def changeset_info(self, repo_name, revision): if request.is_xhr: try: - return c.rhodecode_repo.get_changeset(revision) + return c.db_repo_scm_instance.get_changeset(revision) except ChangesetDoesNotExistError, e: return EmptyChangeset(message=str(e)) else: raise HTTPBadRequest() + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + @jsonify + def changeset_children(self, repo_name, revision): + if request.is_xhr: + changeset = c.db_repo_scm_instance.get_changeset(revision) + result = {"results": []} + if changeset.children: + result = {"results": changeset.children} + return result + else: + raise HTTPBadRequest() + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + @jsonify + def changeset_parents(self, repo_name, revision): + if request.is_xhr: + changeset = c.db_repo_scm_instance.get_changeset(revision) + result = {"results": []} + if changeset.parents: + result = {"results": changeset.parents} + return result + else: + raise HTTPBadRequest() diff --git a/rhodecode/controllers/compare.py b/kallithea/controllers/compare.py rename from rhodecode/controllers/compare.py rename to kallithea/controllers/compare.py --- a/rhodecode/controllers/compare.py +++ b/kallithea/controllers/compare.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.compare - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - compare controller for pylons showing differences between two - repos, branches, bookmarks or tips - - :created_on: May 6, 2012 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,6 +11,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.compare +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +compare controller for pylons showing differences between two +repos, branches, bookmarks or tips + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: May 6, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import traceback @@ -33,16 +36,15 @@ from pylons import request, response, se from pylons.controllers.util import abort, redirect from pylons.i18n.translation import _ -from rhodecode.lib.vcs.exceptions import EmptyRepositoryError, RepositoryError -from rhodecode.lib.vcs.utils import safe_str -from rhodecode.lib.vcs.utils.hgcompat import scmutil, unionrepo -from rhodecode.lib import helpers as h -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator -from rhodecode.lib import diffs -from rhodecode.lib.utils2 import safe_str -from rhodecode.model.db import Repository -from rhodecode.lib.diffs import LimitedDiffContainer +from kallithea.lib.vcs.exceptions import EmptyRepositoryError, RepositoryError +from kallithea.lib.vcs.utils import safe_str +from kallithea.lib.vcs.utils.hgcompat import unionrepo +from kallithea.lib import helpers as h +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from kallithea.lib import diffs +from kallithea.model.db import Repository +from kallithea.lib.diffs import LimitedDiffContainer log = logging.getLogger(__name__) @@ -54,16 +56,17 @@ class CompareController(BaseRepoControll super(CompareController, self).__before__() def __get_rev_or_redirect(self, ref, repo, redirect_after=True, - partial=False): + partial=False): """ Safe way to get changeset if error occur it redirects to changeset with proper message. If partial is set then don't do redirect raise Exception instead - :param rev: revision to fetch - :param repo: repo instance + :param ref: + :param repo: + :param redirect_after: + :param partial: """ - rev = ref[1] # default and used for git if repo.scm_instance.alias == 'hg': # lookup up the exact node id @@ -97,12 +100,17 @@ class CompareController(BaseRepoControll def _get_changesets(self, alias, org_repo, org_rev, other_repo, other_rev, merge): """ - Returns a list of changesets that can be merged from org_repo@org_rev - to other_repo@other_rev ... and the ancestor that would be used for merge + Returns a list of changesets that can be merged from org_repo at org_rev + to other_repo at other_rev ... and the ancestor that would be used for merge. + + :param org_repo: repo object, that is most likely the orginal repo we forked from + :param org_rev: the revision we want our compare to be made + :param other_repo: repo object, mostl likely the fork of org_repo. It hass + all changesets that we need to obtain + :param other_rev: revision we want out compare to be made on other_repo + """ - ancestor = None - if org_rev == other_rev: changesets = [] if merge: @@ -122,10 +130,12 @@ class CompareController(BaseRepoControll hgrepo = other_repo._repo if merge: - revs = hgrepo.revs("ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)", - other_rev, org_rev, org_rev) + revs = hgrepo.revs( + "ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)", + other_rev, org_rev, org_rev) - ancestors = hgrepo.revs("ancestor(id(%s), id(%s))", org_rev, other_rev) + ancestors = hgrepo.revs("ancestor(id(%s), id(%s))", org_rev, + other_rev) if ancestors: # pick arbitrary ancestor - but there is usually only one ancestor = hgrepo[ancestors[0]].hex() @@ -138,24 +148,58 @@ class CompareController(BaseRepoControll elif alias == 'git': if org_repo != other_repo: - raise Exception('Comparing of different GIT repositories is not' - 'allowed. Got %s != %s' % (org_repo, other_repo)) + from dulwich.repo import Repo + from dulwich.client import SubprocessGitClient + + gitrepo = Repo(org_repo.path) + SubprocessGitClient(thin_packs=False).fetch(other_repo.path, gitrepo) + + gitrepo_remote = Repo(other_repo.path) + SubprocessGitClient(thin_packs=False).fetch(org_repo.path, gitrepo_remote) + + revs = [] + for x in gitrepo_remote.get_walker(include=[other_rev], + exclude=[org_rev]): + revs.append(x.commit.id) - so, se = org_repo.run_git_command( - 'log --reverse --pretty="format: %%H" -s -p %s..%s' - % (org_rev, other_rev) - ) - changesets = [org_repo.get_changeset(cs) - for cs in re.findall(r'[0-9a-fA-F]{40}', so)] + changesets = [other_repo.get_changeset(rev) for rev in reversed(revs)] + if changesets: + ancestor = changesets[0].parents[0].raw_id + else: + # no changesets from other repo, ancestor is the other_rev + ancestor = other_rev + + else: + so, se = org_repo.run_git_command( + 'log --reverse --pretty="format: %%H" -s %s..%s' + % (org_rev, other_rev) + ) + changesets = [org_repo.get_changeset(cs) + for cs in re.findall(r'[0-9a-fA-F]{40}', so)] + + else: + raise Exception('Bad alias only git and hg is allowed') return changesets, ancestor @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') - def index(self, org_ref_type, org_ref, other_ref_type, other_ref): + def index(self, repo_name): + c.compare_home = True + org_repo = c.db_repo.repo_name + other_repo = request.GET.get('other_repo', org_repo) + c.org_repo = Repository.get_by_repo_name(org_repo) + c.other_repo = Repository.get_by_repo_name(other_repo) + c.org_ref = c.other_ref = _('Select changeset') + return render('compare/compare_diff.html') + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + def compare(self, repo_name, org_ref_type, org_ref, other_ref_type, other_ref): # org_ref will be evaluated in org_repo - org_repo = c.rhodecode_db_repo.repo_name + org_repo = c.db_repo.repo_name org_ref = (org_ref_type, org_ref) # other_ref will be evaluated in other_repo other_ref = (other_ref_type, other_ref) @@ -187,23 +231,27 @@ class CompareController(BaseRepoControll other_repo = Repository.get_by_repo_name(other_repo) if org_repo is None: - log.error('Could not find org repo %s' % org_repo) - raise HTTPNotFound + msg = 'Could not find org repo %s' % org_repo + log.error(msg) + h.flash(msg, category='error') + return redirect(url('compare_home', repo_name=c.repo_name)) + if other_repo is None: - log.error('Could not find other repo %s' % other_repo) - raise HTTPNotFound - - if org_repo != other_repo and h.is_git(org_repo): - log.error('compare of two remote repos not available for GIT REPOS') - raise HTTPNotFound + msg = 'Could not find other repo %s' % other_repo + log.error(msg) + h.flash(msg, category='error') + return redirect(url('compare_home', repo_name=c.repo_name)) if org_repo.scm_instance.alias != other_repo.scm_instance.alias: - log.error('compare of two different kind of remote repos not available') - raise HTTPNotFound + msg = 'compare of two different kind of remote repos not available' + log.error(msg) + h.flash(msg, category='error') + return redirect(url('compare_home', repo_name=c.repo_name)) org_rev = self.__get_rev_or_redirect(ref=org_ref, repo=org_repo, partial=partial) other_rev = self.__get_rev_or_redirect(ref=other_ref, repo=other_repo, partial=partial) + c.compare_home = False c.org_repo = org_repo c.other_repo = other_repo c.org_ref = org_ref[1] @@ -211,19 +259,17 @@ class CompareController(BaseRepoControll c.org_ref_type = org_ref[0] c.other_ref_type = other_ref[0] - c.cs_ranges, c.ancestor = self._get_changesets(org_repo.scm_instance.alias, - org_repo.scm_instance, org_rev, - other_repo.scm_instance, other_rev, - merge) + c.cs_ranges, c.ancestor = self._get_changesets( + org_repo.scm_instance.alias, org_repo.scm_instance, org_rev, + other_repo.scm_instance, other_rev, merge) + c.statuses = c.db_repo.statuses( + [x.raw_id for x in c.cs_ranges]) - c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in - c.cs_ranges]) if merge and not c.ancestor: log.error('Unable to find ancestor revision') if partial: return render('compare/compare_cs.html') - if c.ancestor: assert merge # case we want a simple diff without incoming changesets, @@ -238,8 +284,8 @@ class CompareController(BaseRepoControll log.debug('running diff between %s and %s in %s' % (org_rev, other_rev, org_repo.scm_instance.path)) + txtdiff = org_repo.scm_instance.get_diff(rev1=org_rev, rev2=other_rev) - diff_processor = diffs.DiffProcessor(txtdiff or '', format='gitdiff', diff_limit=diff_limit) _parsed = diff_processor.prepare() diff --git a/rhodecode/controllers/error.py b/kallithea/controllers/error.py rename from rhodecode/controllers/error.py rename to kallithea/controllers/error.py --- a/rhodecode/controllers/error.py +++ b/kallithea/controllers/error.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.error - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - RhodeCode error controller - - :created_on: Dec 8, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.error +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Kallithea error controller + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Dec 8, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import os import cgi import logging @@ -31,7 +34,7 @@ from pylons import tmpl_context as c, re from pylons.i18n.translation import _ from pylons.middleware import media_path -from rhodecode.lib.base import BaseController, render +from kallithea.lib.base import BaseController, render log = logging.getLogger(__name__) @@ -52,7 +55,7 @@ class ErrorController(BaseController): def document(self): resp = request.environ.get('pylons.original_response') - c.rhodecode_name = config.get('rhodecode_title') + c.site_name = config.get('title') log.debug('### %s ###' % resp.status) diff --git a/rhodecode/controllers/feed.py b/kallithea/controllers/feed.py rename from rhodecode/controllers/feed.py rename to kallithea/controllers/feed.py --- a/rhodecode/controllers/feed.py +++ b/kallithea/controllers/feed.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.feed - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Feed controller for rhodecode - - :created_on: Apr 23, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.feed +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Feed controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 23, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging @@ -31,12 +34,12 @@ from pylons.i18n.translation import _ from beaker.cache import cache_region, region_invalidate from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed -from rhodecode.lib import helpers as h -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator -from rhodecode.lib.base import BaseRepoController -from rhodecode.lib.diffs import DiffProcessor, LimitedDiffContainer -from rhodecode.model.db import CacheInvalidation -from rhodecode.lib.utils2 import safe_int, str2bool, safe_unicode +from kallithea.lib import helpers as h +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from kallithea.lib.base import BaseRepoController +from kallithea.lib.diffs import DiffProcessor, LimitedDiffContainer +from kallithea.model.db import CacheInvalidation +from kallithea.lib.utils2 import safe_int, str2bool, safe_unicode log = logging.getLogger(__name__) @@ -50,11 +53,11 @@ class FeedController(BaseRepoController) super(FeedController, self).__before__() #common values for feeds self.description = _('Changes on %s repository') - self.title = self.title = _('%s %s feed') % (c.rhodecode_name, '%s') + self.title = self.title = _('%s %s feed') % (c.site_name, '%s') self.language = 'en-us' self.ttl = "5" - import rhodecode - CONF = rhodecode.CONFIG + import kallithea + CONF = kallithea.CONFIG self.include_diff = str2bool(CONF.get('rss_include_diff', False)) self.feed_nr = safe_int(CONF.get('rss_items_per_page', 20)) # we need to protect from parsing huge diffs here other way @@ -92,14 +95,14 @@ class FeedController(BaseRepoController) #branches, tags, bookmarks if cs.branch: desc_msg.append('branch: %s
' % cs.branch) - if h.is_hg(c.rhodecode_repo): + if h.is_hg(c.db_repo_scm_instance): for book in cs.bookmarks: desc_msg.append('bookmark: %s
' % book) for tag in cs.tags: desc_msg.append('tag: %s
' % tag) diff_processor, changes = self.__changes(cs) # rev link - _url = url('changeset_home', repo_name=c.rhodecode_db_repo.repo_name, + _url = url('changeset_home', repo_name=c.db_repo.repo_name, revision=cs.raw_id, qualified=True) desc_msg.append('changeset: %s' % (_url, cs.raw_id[:8])) @@ -127,7 +130,7 @@ class FeedController(BaseRepoController) ttl=self.ttl ) - for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])): + for cs in reversed(list(c.db_repo_scm_instance[-self.feed_nr:])): feed.add_item(title=self._get_title(cs), link=url('changeset_home', repo_name=repo_name, revision=cs.raw_id, qualified=True), @@ -159,7 +162,7 @@ class FeedController(BaseRepoController) ttl=self.ttl ) - for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])): + for cs in reversed(list(c.db_repo_scm_instance[-self.feed_nr:])): feed.add_item(title=self._get_title(cs), link=url('changeset_home', repo_name=repo_name, revision=cs.raw_id, qualified=True), diff --git a/rhodecode/controllers/files.py b/kallithea/controllers/files.py rename from rhodecode/controllers/files.py rename to kallithea/controllers/files.py --- a/rhodecode/controllers/files.py +++ b/kallithea/controllers/files.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.files - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Files controller for RhodeCode - - :created_on: Apr 21, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.files +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Files controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 21, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from __future__ import with_statement import os import logging @@ -32,32 +35,32 @@ import shutil from pylons import request, response, tmpl_context as c, url from pylons.i18n.translation import _ from pylons.controllers.util import redirect -from rhodecode.lib.utils import jsonify, action_logger +from kallithea.lib.utils import jsonify, action_logger -from rhodecode.lib import diffs -from rhodecode.lib import helpers as h +from kallithea.lib import diffs +from kallithea.lib import helpers as h -from rhodecode.lib.compat import OrderedDict -from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str,\ +from kallithea.lib.compat import OrderedDict +from kallithea.lib.utils2 import convert_line_endings, detect_mode, safe_str,\ str2bool -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.vcs.conf import settings -from rhodecode.lib.vcs.exceptions import RepositoryError, \ +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.vcs.backends.base import EmptyChangeset +from kallithea.lib.vcs.conf import settings +from kallithea.lib.vcs.exceptions import RepositoryError, \ ChangesetDoesNotExistError, EmptyRepositoryError, \ ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError,\ NodeDoesNotExistError, ChangesetError, NodeError -from rhodecode.lib.vcs.nodes import FileNode +from kallithea.lib.vcs.nodes import FileNode -from rhodecode.model.repo import RepoModel -from rhodecode.model.scm import ScmModel -from rhodecode.model.db import Repository +from kallithea.model.repo import RepoModel +from kallithea.model.scm import ScmModel +from kallithea.model.db import Repository -from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\ +from kallithea.controllers.changeset import anchor_url, _ignorews_url,\ _context_url, get_line_ctx, get_ignore_ws from webob.exc import HTTPNotFound -from rhodecode.lib.exceptions import NonRelativePathError, IMCCommitError +from kallithea.lib.exceptions import NonRelativePathError, IMCCommitError log = logging.getLogger(__name__) @@ -79,19 +82,23 @@ class FilesController(BaseRepoController """ try: - return c.rhodecode_repo.get_changeset(rev) + return c.db_repo_scm_instance.get_changeset(rev) except EmptyRepositoryError, e: if not redirect_after: return None url_ = url('files_add_home', repo_name=c.repo_name, - revision=0, f_path='') - add_new = h.link_to(_('Click here to add new file'), url_) - h.flash(h.literal(_('There are no files yet %s') % add_new), + revision=0, f_path='', anchor='edit') + add_new = h.link_to(_('Click here to add new file'), url_, class_="alert-link") + h.flash(h.literal(_('There are no files yet. %s') % add_new), category='warning') redirect(h.url('summary_home', repo_name=repo_name)) - - except RepositoryError, e: # including ChangesetDoesNotExistError + except(ChangesetDoesNotExistError, LookupError), e: + log.error(traceback.format_exc()) + msg = _('Such revision does not exist for this repository') + h.flash(msg, category='error') + raise HTTPNotFound() + except RepositoryError, e: h.flash(safe_str(e), category='error') raise HTTPNotFound() @@ -109,6 +116,11 @@ class FilesController(BaseRepoController file_node = cs.get_node(path) if file_node.is_dir(): raise RepositoryError('given path is a directory') + except(ChangesetDoesNotExistError,), e: + log.error(traceback.format_exc()) + msg = _('Such revision does not exist for this repository') + h.flash(msg, category='error') + raise HTTPNotFound() except RepositoryError, e: h.flash(safe_str(e), category='error') raise HTTPNotFound() @@ -133,7 +145,7 @@ class FilesController(BaseRepoController # prev link try: - prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch) + prev_rev = c.db_repo_scm_instance.get_changeset(cur_rev).prev(c.branch) c.url_prev = url('files_home', repo_name=c.repo_name, revision=prev_rev.raw_id, f_path=f_path) if c.branch: @@ -143,7 +155,7 @@ class FilesController(BaseRepoController # next link try: - next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch) + next_rev = c.db_repo_scm_instance.get_changeset(cur_rev).next(c.branch) c.url_next = url('files_home', repo_name=c.repo_name, revision=next_rev.raw_id, f_path=f_path) if c.branch: @@ -162,7 +174,7 @@ class FilesController(BaseRepoController if c.changeset.revision < file_last_cs.revision else file_last_cs) #determine if we're on branch head - _branches = c.rhodecode_repo.branches + _branches = c.db_repo_scm_instance.branches c.on_branch_head = revision in _branches.keys() + _branches.values() _hist = [] c.file_history = [] @@ -186,22 +198,40 @@ class FilesController(BaseRepoController @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') - def history(self, repo_name, revision, f_path, annotate=False): - if request.environ.get('HTTP_X_PARTIAL_XHR'): - c.changeset = self.__get_cs_or_redirect(revision, repo_name) - c.f_path = f_path - c.annotate = annotate - c.file = c.changeset.get_node(f_path) - if c.file.is_file(): - file_last_cs = c.file.last_changeset - c.file_changeset = (c.changeset - if c.changeset.revision < file_last_cs.revision - else file_last_cs) - c.file_history, _hist = self._get_node_history(c.changeset, f_path) - c.authors = [] - for a in set([x.author for x in _hist]): - c.authors.append((h.email(a), h.person(a))) - return render('files/files_history_box.html') + @jsonify + def history(self, repo_name, revision, f_path): + changeset = self.__get_cs_or_redirect(revision, repo_name) + f_path = f_path + _file = changeset.get_node(f_path) + if _file.is_file(): + file_history, _hist = self._get_node_history(changeset, f_path) + + res = [] + for obj in file_history: + res.append({ + 'text': obj[1], + 'children': [{'id': o[0], 'text': o[1]} for o in obj[0]] + }) + + data = { + 'more': False, + 'results': res + } + return data + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + def authors(self, repo_name, revision, f_path): + changeset = self.__get_cs_or_redirect(revision, repo_name) + f_path = f_path + _file = changeset.get_node(f_path) + if _file.is_file(): + file_history, _hist = self._get_node_history(changeset, f_path) + c.authors = [] + for a in set([x.author for x in _hist]): + c.authors.append((h.email(a), h.person(a))) + return render('files/files_history_box.html') @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', @@ -265,8 +295,68 @@ class FilesController(BaseRepoController @LoginRequired() @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') + def delete(self, repo_name, revision, f_path): + repo = c.db_repo + if repo.enable_locking and repo.locked[0]: + h.flash(_('This repository is has been locked by %s on %s') + % (h.person_by_id(repo.locked[0]), + h.fmt_date(h.time_to_datetime(repo.locked[1]))), + 'warning') + return redirect(h.url('files_home', + repo_name=repo_name, revision='tip')) + + # check if revision is a branch identifier- basically we cannot + # create multiple heads via file editing + _branches = repo.scm_instance.branches + # check if revision is a branch name or branch hash + if revision not in _branches.keys() + _branches.values(): + h.flash(_('You can only delete files with revision ' + 'being a valid branch '), category='warning') + return redirect(h.url('files_home', + repo_name=repo_name, revision='tip', + f_path=f_path)) + + r_post = request.POST + + c.cs = self.__get_cs_or_redirect(revision, repo_name) + c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path) + + c.default_message = _('Deleted file %s via Kallithea') % (f_path) + c.f_path = f_path + node_path = f_path + author = self.authuser.full_contact + + if r_post: + message = r_post.get('message') or c.default_message + + try: + nodes = { + node_path: { + 'content': '' + } + } + self.scm_model.delete_nodes( + user=c.authuser.user_id, repo=c.db_repo, + message=message, + nodes=nodes, + parent_cs=c.cs, + author=author, + ) + + h.flash(_('Successfully deleted file %s') % f_path, + category='success') + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during commit'), category='error') + return redirect(url('changeset_home', + repo_name=c.repo_name, revision='tip')) + + return render('files/files_delete.html') + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') def edit(self, repo_name, revision, f_path): - repo = c.rhodecode_db_repo + repo = c.db_repo if repo.enable_locking and repo.locked[0]: h.flash(_('This repository is has been locked by %s on %s') % (h.person_by_id(repo.locked[0]), @@ -294,7 +384,7 @@ class FilesController(BaseRepoController if c.file.is_binary: return redirect(url('files_home', repo_name=c.repo_name, revision=c.cs.raw_id, f_path=f_path)) - c.default_message = _('Edited file %s via RhodeCode') % (f_path) + c.default_message = _('Edited file %s via Kallithea') % (f_path) c.f_path = f_path if r_post: @@ -307,16 +397,16 @@ class FilesController(BaseRepoController content = convert_line_endings(r_post.get('content', ''), mode) message = r_post.get('message') or c.default_message - author = self.rhodecode_user.full_contact + author = self.authuser.full_contact if content == old_content: h.flash(_('No changes'), category='warning') return redirect(url('changeset_home', repo_name=c.repo_name, revision='tip')) try: - self.scm_model.commit_change(repo=c.rhodecode_repo, + self.scm_model.commit_change(repo=c.db_repo_scm_instance, repo_name=repo_name, cs=c.cs, - user=self.rhodecode_user.user_id, + user=self.authuser.user_id, author=author, message=message, content=content, f_path=f_path) h.flash(_('Successfully committed to %s') % f_path, @@ -346,8 +436,8 @@ class FilesController(BaseRepoController c.cs = self.__get_cs_or_redirect(revision, repo_name, redirect_after=False) if c.cs is None: - c.cs = EmptyChangeset(alias=c.rhodecode_repo.alias) - c.default_message = (_('Added file via RhodeCode')) + c.cs = EmptyChangeset(alias=c.db_repo_scm_instance.alias) + c.default_message = (_('Added file via Kallithea')) c.f_path = f_path if r_post: @@ -378,7 +468,7 @@ class FilesController(BaseRepoController #strip all crap out of file, just leave the basename filename = os.path.basename(filename) node_path = os.path.join(location, filename) - author = self.rhodecode_user.full_contact + author = self.authuser.full_contact try: nodes = { @@ -387,7 +477,7 @@ class FilesController(BaseRepoController } } self.scm_model.create_nodes( - user=c.rhodecode_user.user_id, repo=c.rhodecode_db_repo, + user=c.authuser.user_id, repo=c.db_repo, message=message, nodes=nodes, parent_cs=c.cs, @@ -433,13 +523,13 @@ class FilesController(BaseRepoController if not dbrepo.enable_downloads: return _('Downloads disabled') - if c.rhodecode_repo.alias == 'hg': + if c.db_repo_scm_instance.alias == 'hg': # patch and reset hooks section of UI config to not run any # hooks on fetching archives with subrepos - for k, v in c.rhodecode_repo._repo.ui.configitems('hooks'): - c.rhodecode_repo._repo.ui.setconfig('hooks', k, None) + for k, v in c.db_repo_scm_instance._repo.ui.configitems('hooks'): + c.db_repo_scm_instance._repo.ui.setconfig('hooks', k, None) - cs = c.rhodecode_repo.get_changeset(revision) + cs = c.db_repo_scm_instance.get_changeset(revision) content_type = settings.ARCHIVE_SPECS[fileformat][0] except ChangesetDoesNotExistError: return _('Unknown revision %s') % revision @@ -448,7 +538,7 @@ class FilesController(BaseRepoController except (ImproperArchiveTypeError, KeyError): return _('Unknown archive type') # archive cache - from rhodecode import CONFIG + from kallithea import CONFIG rev_name = cs.raw_id[:12] archive_name = '%s-%s%s' % (safe_str(repo_name.replace('/', '_')), safe_str(rev_name), ext) @@ -468,19 +558,21 @@ class FilesController(BaseRepoController log.debug('Archive %s is not yet cached' % (archive_name)) if not use_cached_archive: - #generate new archive + # generate new archive + temp_stream = None try: fd, archive = tempfile.mkstemp() - t = open(archive, 'wb') + temp_stream = open(archive, 'wb') log.debug('Creating new temp archive in %s' % archive) - cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos) - if archive_cache_enabled: + cs.fill_archive(stream=temp_stream, kind=fileformat, subrepos=subrepos) + if not subrepos and archive_cache_enabled: #if we generated the archive and use cache rename that log.debug('Storing new archive in %s' % cached_archive_path) shutil.move(archive, cached_archive_path) archive = cached_archive_path finally: - t.close() + if temp_stream: + temp_stream.close() def get_chunked_archive(archive): stream = open(archive, 'rb') @@ -496,7 +588,7 @@ class FilesController(BaseRepoController break yield data # store download action - action_logger(user=c.rhodecode_user, + action_logger(user=c.authuser, action='user_downloaded_archive:%s' % (archive_name), repo=repo_name, ipaddr=self.ip_addr, commit=True) response.content_disposition = str('attachment; filename=%s' % (archive_name)) @@ -535,7 +627,7 @@ class FilesController(BaseRepoController return redirect(_url) try: if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: - c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) + c.changeset_1 = c.db_repo_scm_instance.get_changeset(diff1) try: node1 = c.changeset_1.get_node(f_path) if node1.is_dir(): @@ -544,14 +636,14 @@ class FilesController(BaseRepoController except NodeDoesNotExistError: c.changeset_1 = EmptyChangeset(cs=diff1, revision=c.changeset_1.revision, - repo=c.rhodecode_repo) + repo=c.db_repo_scm_instance) node1 = FileNode(f_path, '', changeset=c.changeset_1) else: - c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo) + c.changeset_1 = EmptyChangeset(repo=c.db_repo_scm_instance) node1 = FileNode(f_path, '', changeset=c.changeset_1) if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]: - c.changeset_2 = c.rhodecode_repo.get_changeset(diff2) + c.changeset_2 = c.db_repo_scm_instance.get_changeset(diff2) try: node2 = c.changeset_2.get_node(f_path) if node2.is_dir(): @@ -560,10 +652,10 @@ class FilesController(BaseRepoController except NodeDoesNotExistError: c.changeset_2 = EmptyChangeset(cs=diff2, revision=c.changeset_2.revision, - repo=c.rhodecode_repo) + repo=c.db_repo_scm_instance) node2 = FileNode(f_path, '', changeset=c.changeset_2) else: - c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) + c.changeset_2 = EmptyChangeset(repo=c.db_repo_scm_instance) node2 = FileNode(f_path, '', changeset=c.changeset_2) except (RepositoryError, NodeError): log.error(traceback.format_exc()) @@ -620,7 +712,7 @@ class FilesController(BaseRepoController diff2 = request.GET.get('diff2', '') try: if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: - c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) + c.changeset_1 = c.db_repo_scm_instance.get_changeset(diff1) try: node1 = c.changeset_1.get_node(f_path) if node1.is_dir(): @@ -629,14 +721,14 @@ class FilesController(BaseRepoController except NodeDoesNotExistError: c.changeset_1 = EmptyChangeset(cs=diff1, revision=c.changeset_1.revision, - repo=c.rhodecode_repo) + repo=c.db_repo_scm_instance) node1 = FileNode(f_path, '', changeset=c.changeset_1) else: - c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo) + c.changeset_1 = EmptyChangeset(repo=c.db_repo_scm_instance) node1 = FileNode(f_path, '', changeset=c.changeset_1) if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]: - c.changeset_2 = c.rhodecode_repo.get_changeset(diff2) + c.changeset_2 = c.db_repo_scm_instance.get_changeset(diff2) try: node2 = c.changeset_2.get_node(f_path) if node2.is_dir(): @@ -645,37 +737,15 @@ class FilesController(BaseRepoController except NodeDoesNotExistError: c.changeset_2 = EmptyChangeset(cs=diff2, revision=c.changeset_2.revision, - repo=c.rhodecode_repo) + repo=c.db_repo_scm_instance) node2 = FileNode(f_path, '', changeset=c.changeset_2) else: - c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) + c.changeset_2 = EmptyChangeset(repo=c.db_repo_scm_instance) node2 = FileNode(f_path, '', changeset=c.changeset_2) except (RepositoryError, NodeError): log.error(traceback.format_exc()) return redirect(url('files_home', repo_name=c.repo_name, f_path=f_path)) - if node2.is_binary: - node2_content = 'binary file' - else: - node2_content = node2.content - - if node1.is_binary: - node1_content = 'binary file' - else: - node1_content = node1.content - - html_escape_table = { - "&": "\u0026", - '"': "\u0022", - "'": "\u0027", - ">": "\u003e", - "<": "\u003c", - '\\': "\u005c", - '\n': '\\n' - } - - c.orig1 = h.html_escape((node1_content), html_escape_table) - c.orig2 = h.html_escape((node2_content), html_escape_table) c.node1 = node1 c.node2 = node2 c.cs1 = c.changeset_1 @@ -693,7 +763,7 @@ class FilesController(BaseRepoController changesets defined in this list """ # calculate history based on tip - tip_cs = c.rhodecode_repo.get_changeset() + tip_cs = c.db_repo_scm_instance.get_changeset() if changesets is None: try: changesets = tip_cs.get_file_history(f_path) @@ -713,11 +783,11 @@ class FilesController(BaseRepoController changesets_group[0].append((chs.raw_id, n_desc,)) hist_l.append(changesets_group) - for name, chs in c.rhodecode_repo.branches.items(): + for name, chs in c.db_repo_scm_instance.branches.items(): branches_group[0].append((chs, name),) hist_l.append(branches_group) - for name, chs in c.rhodecode_repo.tags.items(): + for name, chs in c.db_repo_scm_instance.tags.items(): tags_group[0].append((chs, name),) hist_l.append(tags_group) diff --git a/rhodecode/controllers/followers.py b/kallithea/controllers/followers.py rename from rhodecode/controllers/followers.py rename to kallithea/controllers/followers.py --- a/rhodecode/controllers/followers.py +++ b/kallithea/controllers/followers.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.followers - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Followers controller for rhodecode - - :created_on: Apr 23, 2011 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,15 +11,29 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.followers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Followers controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 23, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging from pylons import tmpl_context as c, request -from rhodecode.lib.helpers import Page -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.model.db import Repository, User, UserFollowing -from rhodecode.lib.utils2 import safe_int +from kallithea.lib.helpers import Page +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from kallithea.lib.base import BaseRepoController, render +from kallithea.model.db import Repository, User, UserFollowing +from kallithea.lib.utils2 import safe_int log = logging.getLogger(__name__) @@ -45,7 +48,7 @@ class FollowersController(BaseRepoContro 'repository.admin') def followers(self, repo_name): p = safe_int(request.GET.get('page', 1), 1) - repo_id = c.rhodecode_db_repo.repo_id + repo_id = c.db_repo.repo_id d = UserFollowing.get_repo_followers(repo_id)\ .order_by(UserFollowing.follows_from) c.followers_pager = Page(d, page=p, items_per_page=20) diff --git a/rhodecode/controllers/forks.py b/kallithea/controllers/forks.py rename from rhodecode/controllers/forks.py rename to kallithea/controllers/forks.py --- a/rhodecode/controllers/forks.py +++ b/kallithea/controllers/forks.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.forks - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - forks controller for rhodecode - - :created_on: Apr 23, 2011 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.forks +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +forks controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 23, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import formencode import traceback @@ -30,20 +33,21 @@ from formencode import htmlfill from pylons import tmpl_context as c, request, url from pylons.controllers.util import redirect from pylons.i18n.translation import _ +from webob.exc import HTTPNotFound, HTTPInternalServerError -import rhodecode.lib.helpers as h +import kallithea.lib.helpers as h -from rhodecode.lib.helpers import Page -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \ - NotAnonymous, HasRepoPermissionAny, HasPermissionAllDecorator,\ - HasPermissionAnyDecorator -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.model.db import Repository, RepoGroup, UserFollowing, User,\ - RhodeCodeUi -from rhodecode.model.repo import RepoModel -from rhodecode.model.forms import RepoForkForm -from rhodecode.model.scm import ScmModel, RepoGroupList -from rhodecode.lib.utils2 import safe_int +from kallithea.lib.helpers import Page +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \ + NotAnonymous, HasRepoPermissionAny, HasPermissionAnyDecorator +from kallithea.lib.base import BaseRepoController, render +from kallithea.model.db import Repository, RepoGroup, UserFollowing, User,\ + Ui +from kallithea.model.repo import RepoModel +from kallithea.model.forms import RepoForkForm +from kallithea.model.scm import ScmModel, RepoGroupList +from kallithea.lib.utils2 import safe_int +from kallithea.lib.utils import jsonify log = logging.getLogger(__name__) @@ -60,7 +64,7 @@ class ForksController(BaseRepoController c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) choices, c.landing_revs = ScmModel().get_repo_landing_revs() c.landing_revs_choices = choices - c.can_update = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_UPDATE).ui_active + c.can_update = Ui.get_by_key(Ui.HOOK_UPDATE).ui_active def __load_data(self, repo_name=None): """ @@ -111,7 +115,7 @@ class ForksController(BaseRepoController 'repository.admin') def forks(self, repo_name): p = safe_int(request.GET.get('page', 1), 1) - repo_id = c.rhodecode_db_repo.repo_id + repo_id = c.db_repo.repo_id d = [] for r in Repository.get_repo_forks(repo_id): if not HasRepoPermissionAny( @@ -160,25 +164,22 @@ class ForksController(BaseRepoController repo_groups=c.repo_groups_choices, landing_revs=c.landing_revs_choices)() form_result = {} + task_id = None try: form_result = _form.to_python(dict(request.POST)) # an approximation that is better than nothing - if not RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_UPDATE).ui_active: + if not Ui.get_by_key(Ui.HOOK_UPDATE).ui_active: form_result['update_after_clone'] = False # create fork is done sometimes async on celery, db transaction # management is handled there. - RepoModel().create_fork(form_result, self.rhodecode_user.user_id) - fork_url = h.link_to(form_result['repo_name_full'], - h.url('summary_home', repo_name=form_result['repo_name_full'])) - - h.flash(h.literal(_('Forked repository %s as %s') \ - % (repo_name, fork_url)), - category='success') + task = RepoModel().create_fork(form_result, self.authuser.user_id) + from celery.result import BaseAsyncResult + if isinstance(task, BaseAsyncResult): + task_id = task.task_id except formencode.Invalid, errors: c.new_repo = errors.value['repo_name'] - return htmlfill.render( render('forks/fork.html'), defaults=errors.value, @@ -190,4 +191,6 @@ class ForksController(BaseRepoController h.flash(_('An error occurred during repository forking %s') % repo_name, category='error') - return redirect(h.url('summary_home', repo_name=repo_name)) + return redirect(h.url('repo_creating_home', + repo_name=form_result['repo_name_full'], + task_id=task_id)) diff --git a/rhodecode/controllers/home.py b/kallithea/controllers/home.py rename from rhodecode/controllers/home.py rename to kallithea/controllers/home.py --- a/rhodecode/controllers/home.py +++ b/kallithea/controllers/home.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.home - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Home controller for Rhodecode - - :created_on: Feb 18, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.home +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Home controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Feb 18, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" import logging @@ -30,13 +33,14 @@ from pylons.i18n.translation import _ from webob.exc import HTTPBadRequest from sqlalchemy.sql.expression import func -import rhodecode -from rhodecode.lib import helpers as h -from rhodecode.lib.compat import json -from rhodecode.lib.auth import LoginRequired -from rhodecode.lib.base import BaseController, render -from rhodecode.model.db import Repository -from rhodecode.model.repo import RepoModel +import kallithea +from kallithea.lib import helpers as h +from kallithea.lib.utils import jsonify, conditional_cache +from kallithea.lib.compat import json +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from kallithea.lib.base import BaseController, render +from kallithea.model.db import Repository, RepoGroup +from kallithea.model.repo import RepoModel log = logging.getLogger(__name__) @@ -47,9 +51,12 @@ class HomeController(BaseController): def __before__(self): super(HomeController, self).__before__() + def about(self): + return render('/about.html') + @LoginRequired() def index(self): - c.groups = self.scm_model.get_repos_groups() + c.groups = self.scm_model.get_repo_groups() c.group = None c.repos_list = Repository.query()\ @@ -65,21 +72,80 @@ class HomeController(BaseController): return render('/index.html') @LoginRequired() - def repo_switcher(self): - if request.is_xhr: + @jsonify + def repo_switcher_data(self): + #wrapper for conditional cache + def _c(): + log.debug('generating switcher repo/groups list') all_repos = Repository.query().order_by(Repository.repo_name).all() - c.repos_list = self.scm_model.get_repos(all_repos, - sort_key='name_sort', - simple=True) - return render('/repo_switcher_list.html') + repo_iter = self.scm_model.get_repos(all_repos, simple=True) + all_groups = RepoGroup.query().order_by(RepoGroup.group_name).all() + repo_groups_iter = self.scm_model.get_repo_groups(all_groups) + + res = [{ + 'text': _('Groups'), + 'children': [ + {'id': obj.group_name, 'text': obj.group_name, + 'type': 'group', 'obj': {}} for obj in repo_groups_iter] + }, { + 'text': _('Repositories'), + 'children': [ + {'id': obj['name'], 'text': obj['name'], + 'type': 'repo', 'obj': obj['dbrepo']} for obj in repo_iter] + }] + + data = { + 'more': False, + 'results': res + } + return data + + if request.is_xhr: + condition = False + compute = conditional_cache('short_term', 'cache_desc', + condition=condition, func=_c) + return compute() else: raise HTTPBadRequest() @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') def branch_tag_switcher(self, repo_name): if request.is_xhr: - c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name) - if c.rhodecode_db_repo: - c.rhodecode_repo = c.rhodecode_db_repo.scm_instance + c.db_repo = Repository.get_by_repo_name(repo_name) + if c.db_repo: + c.db_repo_scm_instance = c.db_repo.scm_instance return render('/switch_to_list.html') raise HTTPBadRequest() + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + @jsonify + def repo_refs_data(self, repo_name): + repo = Repository.get_by_repo_name(repo_name).scm_instance + res = [] + _branches = repo.branches.items() + if _branches: + res.append({ + 'text': _('Branch'), + 'children': [{'id': rev, 'text': name, 'type': 'branch'} for name, rev in _branches] + }) + _tags = repo.tags.items() + if _tags: + res.append({ + 'text': _('Tag'), + 'children': [{'id': rev, 'text': name, 'type': 'tag'} for name, rev in _tags] + }) + _bookmarks = repo.bookmarks.items() + if _bookmarks: + res.append({ + 'text': _('Bookmark'), + 'children': [{'id': rev, 'text': name, 'type': 'book'} for name, rev in _bookmarks] + }) + data = { + 'more': False, + 'results': res + } + return data diff --git a/rhodecode/controllers/journal.py b/kallithea/controllers/journal.py rename from rhodecode/controllers/journal.py rename to kallithea/controllers/journal.py --- a/rhodecode/controllers/journal.py +++ b/kallithea/controllers/journal.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.journal - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Journal controller for pylons - - :created_on: Nov 21, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.journal +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Journal controller for pylons + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Nov 21, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" + import logging from itertools import groupby @@ -35,16 +39,16 @@ from webob.exc import HTTPBadRequest from pylons import request, tmpl_context as c, response, url from pylons.i18n.translation import _ -from rhodecode.controllers.admin.admin import _journal_filter -from rhodecode.model.db import UserLog, UserFollowing, Repository, User -from rhodecode.model.meta import Session -from rhodecode.model.repo import RepoModel -import rhodecode.lib.helpers as h -from rhodecode.lib.helpers import Page -from rhodecode.lib.auth import LoginRequired, NotAnonymous -from rhodecode.lib.base import BaseController, render -from rhodecode.lib.utils2 import safe_int, AttributeDict -from rhodecode.lib.compat import json +from kallithea.controllers.admin.admin import _journal_filter +from kallithea.model.db import UserLog, UserFollowing, Repository, User +from kallithea.model.meta import Session +from kallithea.model.repo import RepoModel +import kallithea.lib.helpers as h +from kallithea.lib.helpers import Page +from kallithea.lib.auth import LoginRequired, NotAnonymous +from kallithea.lib.base import BaseController, render +from kallithea.lib.utils2 import safe_int, AttributeDict +from kallithea.lib.compat import json log = logging.getLogger(__name__) @@ -107,11 +111,11 @@ class JournalController(BaseController): journal = self._get_journal_data(repos) if public: _link = url('public_journal_atom', qualified=True) - _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'), + _desc = '%s %s %s' % (c.site_name, _('public journal'), 'atom feed') else: _link = url('journal_atom', qualified=True) - _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'atom feed') + _desc = '%s %s %s' % (c.site_name, _('journal'), 'atom feed') feed = Atom1Feed(title=_desc, link=_link, @@ -150,11 +154,11 @@ class JournalController(BaseController): journal = self._get_journal_data(repos) if public: _link = url('public_journal_atom', qualified=True) - _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'), + _desc = '%s %s %s' % (c.site_name, _('public journal'), 'rss feed') else: _link = url('journal_atom', qualified=True) - _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'rss feed') + _desc = '%s %s %s' % (c.site_name, _('journal'), 'rss feed') feed = Rss201rev2Feed(title=_desc, link=_link, @@ -194,9 +198,9 @@ class JournalController(BaseController): def index(self): # Return a rendered template p = safe_int(request.GET.get('page', 1), 1) - c.user = User.get(self.rhodecode_user.user_id) + c.user = User.get(self.authuser.user_id) c.following = self.sa.query(UserFollowing)\ - .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\ + .filter(UserFollowing.user_id == self.authuser.user_id)\ .options(joinedload(UserFollowing.follows_repository))\ .all() @@ -214,7 +218,7 @@ class JournalController(BaseController): repos_list = Session().query(Repository)\ .filter(Repository.user_id == - self.rhodecode_user.user_id)\ + self.authuser.user_id)\ .order_by(func.lower(Repository.repo_name)).all() repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, @@ -230,8 +234,8 @@ class JournalController(BaseController): def quick_menu(repo_name): return _render('quick_menu', repo_name) - def repo_lnk(name, rtype, private, fork_of): - return _render('repo_name', name, rtype, private, fork_of, + def repo_lnk(name, rtype, rstate, private, fork_of): + return _render('repo_name', name, rtype, rstate, private, fork_of, short_name=False, admin=False) def last_rev(repo_name, cs_cache): @@ -262,9 +266,9 @@ class JournalController(BaseController): "menu": quick_menu(repo.repo_name), "raw_name": repo.repo_name.lower(), "name": repo_lnk(repo.repo_name, repo.repo_type, - repo.private, repo.fork), + repo.repo_state, repo.private, repo.fork), "last_changeset": last_rev(repo.repo_name, cs_cache), - "raw_tip": cs_cache.get('revision'), + "last_rev_raw": cs_cache.get('revision'), "action": toogle_follow(repo.repo_id) } @@ -286,7 +290,7 @@ class JournalController(BaseController): Produce an atom-1.0 feed via feedgenerator module """ following = self.sa.query(UserFollowing)\ - .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\ + .filter(UserFollowing.user_id == self.authuser.user_id)\ .options(joinedload(UserFollowing.follows_repository))\ .all() return self._atom_feed(following, public=False) @@ -298,7 +302,7 @@ class JournalController(BaseController): Produce an rss feed via feedgenerator module """ following = self.sa.query(UserFollowing)\ - .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\ + .filter(UserFollowing.user_id == self.authuser.user_id)\ .options(joinedload(UserFollowing.follows_repository))\ .all() return self._rss_feed(following, public=False) @@ -314,7 +318,7 @@ class JournalController(BaseController): if user_id: try: self.scm_model.toggle_following_user(user_id, - self.rhodecode_user.user_id) + self.authuser.user_id) Session.commit() return 'ok' except Exception: @@ -324,7 +328,7 @@ class JournalController(BaseController): if repo_id: try: self.scm_model.toggle_following_repo(repo_id, - self.rhodecode_user.user_id) + self.authuser.user_id) Session.commit() return 'ok' except Exception: @@ -339,7 +343,7 @@ class JournalController(BaseController): p = safe_int(request.GET.get('page', 1), 1) c.following = self.sa.query(UserFollowing)\ - .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\ + .filter(UserFollowing.user_id == self.authuser.user_id)\ .options(joinedload(UserFollowing.follows_repository))\ .all() @@ -360,7 +364,7 @@ class JournalController(BaseController): Produce an atom-1.0 feed via feedgenerator module """ c.following = self.sa.query(UserFollowing)\ - .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\ + .filter(UserFollowing.user_id == self.authuser.user_id)\ .options(joinedload(UserFollowing.follows_repository))\ .all() @@ -372,7 +376,7 @@ class JournalController(BaseController): Produce an rss2 feed via feedgenerator module """ c.following = self.sa.query(UserFollowing)\ - .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\ + .filter(UserFollowing.user_id == self.authuser.user_id)\ .options(joinedload(UserFollowing.follows_repository))\ .all() diff --git a/rhodecode/controllers/login.py b/kallithea/controllers/login.py rename from rhodecode/controllers/login.py rename to kallithea/controllers/login.py --- a/rhodecode/controllers/login.py +++ b/kallithea/controllers/login.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.login - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Login controller for rhodeocode - - :created_on: Apr 22, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.login +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Login controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 22, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import formencode @@ -31,17 +34,18 @@ import urlparse from formencode import htmlfill from webob.exc import HTTPFound from pylons.i18n.translation import _ -from pylons.controllers.util import abort, redirect -from pylons import request, response, session, tmpl_context as c, url +from pylons.controllers.util import redirect +from pylons import request, session, tmpl_context as c, url -import rhodecode.lib.helpers as h -from rhodecode.lib.auth import AuthUser, HasPermissionAnyDecorator -from rhodecode.lib.base import BaseController, render -from rhodecode.lib.exceptions import UserCreationError -from rhodecode.model.db import User -from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm -from rhodecode.model.user import UserModel -from rhodecode.model.meta import Session +import kallithea.lib.helpers as h +from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator +from kallithea.lib.auth_modules import importplugin +from kallithea.lib.base import BaseController, render +from kallithea.lib.exceptions import UserCreationError +from kallithea.model.db import User, Setting +from kallithea.model.forms import LoginForm, RegisterForm, PasswordResetForm +from kallithea.model.user import UserModel +from kallithea.model.meta import Session log = logging.getLogger(__name__) @@ -52,13 +56,63 @@ class LoginController(BaseController): def __before__(self): super(LoginController, self).__before__() + def _store_user_in_session(self, username, remember=False): + user = User.get_by_username(username, case_insensitive=True) + auth_user = AuthUser(user.user_id) + auth_user.set_authenticated() + cs = auth_user.get_cookie_store() + session['authuser'] = cs + user.update_lastlogin() + Session().commit() + + # If they want to be remembered, update the cookie + if remember: + _year = (datetime.datetime.now() + + datetime.timedelta(seconds=60 * 60 * 24 * 365)) + session._set_cookie_expires(_year) + + session.save() + + log.info('user %s is now authenticated and stored in ' + 'session, session attrs %s' % (username, cs)) + + # dumps session attrs back to cookie + session._update_cookie_out() + # we set new cookie + headers = None + if session.request['set_cookie']: + # send set-cookie headers back to response to update cookie + headers = [('Set-Cookie', session.request['cookie_out'])] + return headers + + def _validate_came_from(self, came_from): + if not came_from: + return came_from + + parsed = urlparse.urlparse(came_from) + server_parsed = urlparse.urlparse(url.current()) + allowed_schemes = ['http', 'https'] + if parsed.scheme and parsed.scheme not in allowed_schemes: + log.error('Suspicious URL scheme detected %s for url %s' % + (parsed.scheme, parsed)) + came_from = url('home') + elif server_parsed.netloc != parsed.netloc: + log.error('Suspicious NETLOC detected %s for url %s server url ' + 'is: %s' % (parsed.netloc, parsed, server_parsed)) + came_from = url('home') + return came_from + def index(self): + _default_came_from = url('home') + came_from = self._validate_came_from(request.GET.get('came_from')) + c.came_from = came_from or _default_came_from + + not_default = self.authuser.username != User.DEFAULT_USER + ip_allowed = self.authuser.ip_allowed + # redirect if already logged in - c.came_from = request.GET.get('came_from') - not_default = self.rhodecode_user.username != 'default' - ip_allowed = self.rhodecode_user.ip_allowed - if self.rhodecode_user.is_authenticated and not_default and ip_allowed: - return redirect(url('home')) + if self.authuser.is_authenticated and not_default and ip_allowed: + raise HTTPFound(location=c.came_from) if request.POST: # import Login Form validator class @@ -67,53 +121,10 @@ class LoginController(BaseController): session.invalidate() c.form_result = login_form.to_python(dict(request.POST)) # form checks for username/password, now we're authenticated - username = c.form_result['username'] - user = User.get_by_username(username, case_insensitive=True) - auth_user = AuthUser(user.user_id) - auth_user.set_authenticated() - cs = auth_user.get_cookie_store() - session['rhodecode_user'] = cs - user.update_lastlogin() - Session().commit() - - # If they want to be remembered, update the cookie - if c.form_result['remember']: - _year = (datetime.datetime.now() + - datetime.timedelta(seconds=60 * 60 * 24 * 365)) - session._set_cookie_expires(_year) - - session.save() - - log.info('user %s is now authenticated and stored in ' - 'session, session attrs %s' % (username, cs)) - - # dumps session attrs back to cookie - session._update_cookie_out() - - # we set new cookie - headers = None - if session.request['set_cookie']: - # send set-cookie headers back to response to update cookie - headers = [('Set-Cookie', session.request['cookie_out'])] - - allowed_schemes = ['http', 'https'] - if c.came_from: - parsed = urlparse.urlparse(c.came_from) - server_parsed = urlparse.urlparse(url.current()) - if parsed.scheme and parsed.scheme not in allowed_schemes: - log.error( - 'Suspicious URL scheme detected %s for url %s' % - (parsed.scheme, parsed)) - c.came_from = url('home') - elif server_parsed.netloc != parsed.netloc: - log.error('Suspicious NETLOC detected %s for url %s' - 'server url is: %s' % - (parsed.netloc, parsed, server_parsed)) - c.came_from = url('home') - raise HTTPFound(location=c.came_from, headers=headers) - else: - raise HTTPFound(location=url('home'), headers=headers) - + headers = self._store_user_in_session( + username=c.form_result['username'], + remember=c.form_result['remember']) + raise HTTPFound(location=c.came_from, headers=headers) except formencode.Invalid, errors: defaults = errors.value # remove password from filling in form again @@ -131,6 +142,21 @@ class LoginController(BaseController): # Exception itself h.flash(e, 'error') + # check if we use container plugin, and try to login using it. + auth_plugins = Setting.get_auth_plugins() + if any((importplugin(name).is_container_auth for name in auth_plugins)): + from kallithea.lib import auth_modules + try: + auth_info = auth_modules.authenticate('', '', request.environ) + except UserCreationError, e: + log.error(e) + h.flash(e, 'error') + # render login, with flash message about limit + return render('/login.html') + + if auth_info: + headers = self._store_user_in_session(auth_info.get('username')) + raise HTTPFound(location=c.came_from, headers=headers) return render('/login.html') @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate', @@ -139,14 +165,33 @@ class LoginController(BaseController): c.auto_active = 'hg.register.auto_activate' in User.get_default_user()\ .AuthUser.permissions['global'] + settings = Setting.get_app_settings() + captcha_private_key = settings.get('captcha_private_key') + c.captcha_active = bool(captcha_private_key) + c.captcha_public_key = settings.get('captcha_public_key') + if request.POST: register_form = RegisterForm()() try: form_result = register_form.to_python(dict(request.POST)) form_result['active'] = c.auto_active + + if c.captcha_active: + from kallithea.lib.recaptcha import submit + response = submit(request.POST.get('recaptcha_challenge_field'), + request.POST.get('recaptcha_response_field'), + private_key=captcha_private_key, + remoteip=self.ip_addr) + if c.captcha_active and not response.is_valid: + _value = form_result + _msg = _('bad captcha') + error_dict = {'recaptcha_field': _msg} + raise formencode.Invalid(_msg, _value, None, + error_dict=error_dict) + UserModel().create_registration(form_result) - h.flash(_('You have successfully registered into RhodeCode'), - category='success') + h.flash(_('You have successfully registered into Kallithea'), + category='success') Session().commit() return redirect(url('login_home')) @@ -167,10 +212,27 @@ class LoginController(BaseController): return render('/register.html') def password_reset(self): + settings = Setting.get_app_settings() + captcha_private_key = settings.get('captcha_private_key') + c.captcha_active = bool(captcha_private_key) + c.captcha_public_key = settings.get('captcha_public_key') + if request.POST: password_reset_form = PasswordResetForm()() try: form_result = password_reset_form.to_python(dict(request.POST)) + if c.captcha_active: + from kallithea.lib.recaptcha import submit + response = submit(request.POST.get('recaptcha_challenge_field'), + request.POST.get('recaptcha_response_field'), + private_key=captcha_private_key, + remoteip=self.ip_addr) + if c.captcha_active and not response.is_valid: + _value = form_result + _msg = _('bad captcha') + error_dict = {'recaptcha_field': _msg} + raise formencode.Invalid(_msg, _value, None, + error_dict=error_dict) UserModel().reset_password_link(form_result) h.flash(_('Your password reset link was sent'), category='success') diff --git a/rhodecode/controllers/pullrequests.py b/kallithea/controllers/pullrequests.py rename from rhodecode/controllers/pullrequests.py rename to kallithea/controllers/pullrequests.py --- a/rhodecode/controllers/pullrequests.py +++ b/kallithea/controllers/pullrequests.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.pullrequests - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - pull requests controller for rhodecode for initializing pull requests - - :created_on: May 7, 2012 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.pullrequests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +pull requests controller for Kallithea for initializing pull requests + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: May 7, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import traceback import formencode @@ -34,25 +37,25 @@ from pylons import request, tmpl_context from pylons.controllers.util import redirect from pylons.i18n.translation import _ -from rhodecode.lib.compat import json -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\ +from kallithea.lib.compat import json +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\ NotAnonymous -from rhodecode.lib.helpers import Page -from rhodecode.lib import helpers as h -from rhodecode.lib import diffs -from rhodecode.lib.utils import action_logger, jsonify -from rhodecode.lib.vcs.utils import safe_str -from rhodecode.lib.vcs.exceptions import EmptyRepositoryError -from rhodecode.lib.diffs import LimitedDiffContainer -from rhodecode.model.db import PullRequest, ChangesetStatus, ChangesetComment -from rhodecode.model.pull_request import PullRequestModel -from rhodecode.model.meta import Session -from rhodecode.model.repo import RepoModel -from rhodecode.model.comment import ChangesetCommentsModel -from rhodecode.model.changeset_status import ChangesetStatusModel -from rhodecode.model.forms import PullRequestForm -from rhodecode.lib.utils2 import safe_int +from kallithea.lib.helpers import Page +from kallithea.lib import helpers as h +from kallithea.lib import diffs +from kallithea.lib.utils import action_logger, jsonify +from kallithea.lib.vcs.utils import safe_str +from kallithea.lib.vcs.exceptions import EmptyRepositoryError +from kallithea.lib.diffs import LimitedDiffContainer +from kallithea.model.db import PullRequest, ChangesetStatus, ChangesetComment +from kallithea.model.pull_request import PullRequestModel +from kallithea.model.meta import Session +from kallithea.model.repo import RepoModel +from kallithea.model.comment import ChangesetCommentsModel +from kallithea.model.changeset_status import ChangesetStatusModel +from kallithea.model.forms import PullRequestForm +from kallithea.lib.utils2 import safe_int log = logging.getLogger(__name__) @@ -63,7 +66,7 @@ class PullrequestsController(BaseRepoCon super(PullrequestsController, self).__before__() repo_model = RepoModel() c.users_array = repo_model.get_users_js() - c.users_groups_array = repo_model.get_users_groups_js() + c.user_groups_array = repo_model.get_user_groups_js() def _get_repo_refs(self, repo, rev=None, branch=None, branch_rev=None): """return a structure with repo's interesting changesets, suitable for @@ -106,7 +109,8 @@ class PullrequestsController(BaseRepoCon if branch == abranch: selected = n branch = None - if branch: # branch not in list - it is probably closed + + if branch: # branch not in list - it is probably closed revs = repo._repo.revs('max(branch(%s))', branch) if revs: cs = repo.get_changeset(revs[0]) @@ -124,7 +128,7 @@ class PullrequestsController(BaseRepoCon for tag, tagrev in repo.tags.iteritems(): n = 'tag:%s:%s' % (tag, tagrev) tags.append((n, tag)) - if rev == tagrev and tag != 'tip': # tip is not a real tag - and its branch is better + if rev == tagrev and tag != 'tip': # tip is not a real tag - and its branch is better selected = n # prio 1: rev was selected as existing entry above @@ -141,7 +145,14 @@ class PullrequestsController(BaseRepoCon # prio 4: tip revision if not selected: - selected = 'tag:tip:%s' % repo.tags['tip'] + if h.is_hg(repo): + selected = 'tag:tip:%s' % repo.tags['tip'] + else: + if 'master' in repo.branches: + selected = 'branch:master:%s' % repo.branches['master'] + else: + k, v = repo.branches.items()[0] + selected = 'branch:%s:%s' % (k, v) groups = [(specials, _("Special")), (peers, _("Peer branches")), @@ -152,10 +163,10 @@ class PullrequestsController(BaseRepoCon return [g for g in groups if g[0]], selected def _get_is_allowed_change_status(self, pull_request): - owner = self.rhodecode_user.user_id == pull_request.user_id - reviewer = self.rhodecode_user.user_id in [x.user_id for x in + owner = self.authuser.user_id == pull_request.user_id + reviewer = self.authuser.user_id in [x.user_id for x in pull_request.reviewers] - return (self.rhodecode_user.admin or owner or reviewer) + return self.authuser.admin or owner or reviewer def _load_compare_data(self, pull_request, enable_comments=True): """ @@ -246,11 +257,7 @@ class PullrequestsController(BaseRepoCon @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') def index(self): - org_repo = c.rhodecode_db_repo - - if org_repo.scm_instance.alias != 'hg': - log.error('Review not available for GIT REPOS') - raise HTTPNotFound + org_repo = c.db_repo try: org_repo.scm_instance.get_changeset() @@ -340,7 +347,7 @@ class PullrequestsController(BaseRepoCon description = _form['pullrequest_desc'] try: pull_request = PullRequestModel().create( - self.rhodecode_user.user_id, org_repo, org_ref, other_repo, + self.authuser.user_id, org_repo, org_ref, other_repo, other_ref, revisions, reviewers, title, description ) Session().commit() @@ -365,10 +372,11 @@ class PullrequestsController(BaseRepoCon if pull_request.is_closed(): raise HTTPForbidden() #only owner or admin can update it - owner = pull_request.author.user_id == c.rhodecode_user.user_id - if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner: + owner = pull_request.author.user_id == c.authuser.user_id + repo_admin = h.HasRepoPermissionAny('repository.admin')(c.repo_name) + if h.HasPermissionAny('hg.admin') or repo_admin or owner: reviewers_ids = map(int, filter(lambda v: v not in [None, ''], - request.POST.get('reviewers_ids', '').split(','))) + request.POST.get('reviewers_ids', '').split(','))) PullRequestModel().update_reviewers(pull_request_id, reviewers_ids) Session().commit() @@ -383,12 +391,12 @@ class PullrequestsController(BaseRepoCon def delete(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) #only owner can delete it ! - if pull_request.author.user_id == c.rhodecode_user.user_id: + if pull_request.author.user_id == c.authuser.user_id: PullRequestModel().delete(pull_request) Session().commit() h.flash(_('Successfully deleted pull request'), category='success') - return redirect(url('admin_settings_my_account', anchor='pullrequests')) + return redirect(url('my_account_pullrequests')) raise HTTPForbidden() @LoginRequired() @@ -397,7 +405,7 @@ class PullrequestsController(BaseRepoCon def show(self, repo_name, pull_request_id): repo_model = RepoModel() c.users_array = repo_model.get_users_js() - c.users_groups_array = repo_model.get_users_groups_js() + c.user_groups_array = repo_model.get_user_groups_js() c.pull_request = PullRequest.get_or_404(pull_request_id) c.allowed_to_change_status = self._get_is_allowed_change_status(c.pull_request) cc_model = ChangesetCommentsModel() @@ -434,14 +442,14 @@ class PullrequestsController(BaseRepoCon # inline comments c.inline_cnt = 0 c.inline_comments = cc_model.get_inline_comments( - c.rhodecode_db_repo.repo_id, + c.db_repo.repo_id, pull_request=pull_request_id) # count inline comments for __, lines in c.inline_comments: for comments in lines.values(): c.inline_cnt += len(comments) # comments - c.comments = cc_model.get_comments(c.rhodecode_db_repo.repo_id, + c.comments = cc_model.get_comments(c.db_repo.repo_id, pull_request=pull_request_id) # (badly named) pull-request status calculation based on reviewer votes @@ -478,8 +486,8 @@ class PullrequestsController(BaseRepoCon text = text or _def comm = ChangesetCommentsModel().create( text=text, - repo=c.rhodecode_db_repo.repo_id, - user=c.rhodecode_user.user_id, + repo=c.db_repo.repo_id, + user=c.authuser.user_id, pull_request=pull_request_id, f_path=request.POST.get('f_path'), line_no=request.POST.get('line'), @@ -489,17 +497,17 @@ class PullrequestsController(BaseRepoCon closing_pr=close_pr ) - action_logger(self.rhodecode_user, + action_logger(self.authuser, 'user_commented_pull_request:%s' % pull_request_id, - c.rhodecode_db_repo, self.ip_addr, self.sa) + c.db_repo, self.ip_addr, self.sa) if allowed_to_change_status: # get status if set ! if status and change_status: ChangesetStatusModel().set_status( - c.rhodecode_db_repo.repo_id, + c.db_repo.repo_id, status, - c.rhodecode_user.user_id, + c.authuser.user_id, comm, pull_request=pull_request_id ) @@ -507,9 +515,9 @@ class PullrequestsController(BaseRepoCon if close_pr: if status in ['rejected', 'approved']: PullRequestModel().close_pull_request(pull_request_id) - action_logger(self.rhodecode_user, + action_logger(self.authuser, 'user_closed_pull_request:%s' % pull_request_id, - c.rhodecode_db_repo, self.ip_addr, self.sa) + c.db_repo, self.ip_addr, self.sa) else: h.flash(_('Closing pull request on other statuses than ' 'rejected or approved forbidden'), @@ -543,8 +551,9 @@ class PullrequestsController(BaseRepoCon #don't allow deleting comments on closed pull request raise HTTPForbidden() - owner = co.author.user_id == c.rhodecode_user.user_id - if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner: + owner = co.author.user_id == c.authuser.user_id + repo_admin = h.HasRepoPermissionAny('repository.admin')(c.repo_name) + if h.HasPermissionAny('hg.admin') or repo_admin or owner: ChangesetCommentsModel().delete(comment=co) Session().commit() return True diff --git a/rhodecode/controllers/search.py b/kallithea/controllers/search.py rename from rhodecode/controllers/search.py rename to kallithea/controllers/search.py --- a/rhodecode/controllers/search.py +++ b/kallithea/controllers/search.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.search - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Search controller for RhodeCode - - :created_on: Aug 7, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.search +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Search controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Aug 7, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import traceback import urllib @@ -33,13 +36,13 @@ from whoosh.qparser import QueryParser, from whoosh.query import Phrase, Wildcard, Term, Prefix from webhelpers.util import update_params -from rhodecode.lib.auth import LoginRequired -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.indexers import CHGSETS_SCHEMA, SCHEMA, CHGSET_IDX_NAME, \ +from kallithea.lib.auth import LoginRequired +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.indexers import CHGSETS_SCHEMA, SCHEMA, CHGSET_IDX_NAME, \ IDX_NAME, WhooshResultWrapper -from rhodecode.model.repo import RepoModel -from rhodecode.lib.utils2 import safe_str, safe_int -from rhodecode.lib.helpers import Page +from kallithea.model.repo import RepoModel +from kallithea.lib.utils2 import safe_str, safe_int +from kallithea.lib.helpers import Page log = logging.getLogger(__name__) diff --git a/rhodecode/controllers/summary.py b/kallithea/controllers/summary.py rename from rhodecode/controllers/summary.py rename to kallithea/controllers/summary.py --- a/rhodecode/controllers/summary.py +++ b/kallithea/controllers/summary.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.summary - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Summary controller for Rhodecode - - :created_on: Apr 18, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.summary +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Summary controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 18, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import traceback import calendar @@ -37,25 +39,23 @@ from webob.exc import HTTPBadRequest from beaker.cache import cache_region, region_invalidate -from rhodecode.lib import helpers as h -from rhodecode.lib.compat import product -from rhodecode.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, \ +from kallithea.lib.compat import product +from kallithea.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, \ NodeDoesNotExistError -from rhodecode.config.conf import ALL_READMES, ALL_EXTS, LANGUAGES_EXTENSIONS_MAP -from rhodecode.model.db import Statistics, CacheInvalidation -from rhodecode.lib.utils import jsonify -from rhodecode.lib.utils2 import safe_unicode, safe_str -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\ +from kallithea.config.conf import ALL_READMES, ALL_EXTS, LANGUAGES_EXTENSIONS_MAP +from kallithea.model.db import Statistics, CacheInvalidation, User +from kallithea.lib.utils import jsonify +from kallithea.lib.utils2 import safe_unicode, safe_str +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\ NotAnonymous -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.markup_renderer import MarkupRenderer -from rhodecode.lib.celerylib import run_task -from rhodecode.lib.celerylib.tasks import get_commits_stats -from rhodecode.lib.helpers import RepoPage -from rhodecode.lib.compat import json, OrderedDict -from rhodecode.lib.vcs.nodes import FileNode -from rhodecode.controllers.changelog import _load_changelog_summary +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.vcs.backends.base import EmptyChangeset +from kallithea.lib.markup_renderer import MarkupRenderer +from kallithea.lib.celerylib import run_task +from kallithea.lib.celerylib.tasks import get_commits_stats +from kallithea.lib.compat import json +from kallithea.lib.vcs.nodes import FileNode +from kallithea.controllers.changelog import _load_changelog_summary log = logging.getLogger(__name__) @@ -76,12 +76,12 @@ class SummaryController(BaseRepoControll branches_group = ([], _("Branches")) tags_group = ([], _("Tags")) - for name, chs in c.rhodecode_repo.branches.items(): + for name, chs in c.db_repo_scm_instance.branches.items(): #chs = chs.split(':')[-1] branches_group[0].append((chs, name),) download_l.append(branches_group) - for name, chs in c.rhodecode_repo.tags.items(): + for name, chs in c.db_repo_scm_instance.tags.items(): #chs = chs.split(':')[-1] tags_group[0].append((chs, name),) download_l.append(tags_group) @@ -90,12 +90,12 @@ class SummaryController(BaseRepoControll def __get_readme_data(self, db_repo): repo_name = db_repo.repo_name + log.debug('Looking for README file') @cache_region('long_term') def _get_readme_from_cache(key, kind): readme_data = None readme_file = None - log.debug('Looking for README file') try: # gets the landing revision! or tip if fails cs = db_repo.get_landing_changeset() @@ -110,7 +110,8 @@ class SummaryController(BaseRepoControll readme_file = f log.debug('Found README file `%s` rendering...' % readme_file) - readme_data = renderer.render(readme.content, f) + readme_data = renderer.render(readme.content, + filename=f) break except NodeDoesNotExistError: continue @@ -134,40 +135,75 @@ class SummaryController(BaseRepoControll @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') def index(self, repo_name): - c.dbrepo = dbrepo = c.rhodecode_db_repo _load_changelog_summary() - if self.rhodecode_user.username == 'default': - # for default(anonymous) user we don't need to pass credentials - username = '' - password = '' + + username = '' + if self.authuser.username != User.DEFAULT_USER: + username = safe_str(self.authuser.username) + + _def_clone_uri = _def_clone_uri_by_id = c.clone_uri_tmpl + if '{repo}' in _def_clone_uri: + _def_clone_uri_by_id = _def_clone_uri.replace('{repo}', '_{repoid}') + elif '{repoid}' in _def_clone_uri: + _def_clone_uri_by_id = _def_clone_uri.replace('_{repoid}', '{repo}') + + c.clone_repo_url = c.db_repo.clone_url(user=username, + uri_tmpl=_def_clone_uri) + c.clone_repo_url_id = c.db_repo.clone_url(user=username, + uri_tmpl=_def_clone_uri_by_id) + + if c.db_repo.enable_statistics: + c.show_stats = True else: - username = str(self.rhodecode_user.username) - password = '@' + c.show_stats = False + + stats = self.sa.query(Statistics)\ + .filter(Statistics.repository == c.db_repo)\ + .scalar() - parsed_url = urlparse(url.current(qualified=True)) + c.stats_percentage = 0 - default_clone_uri = '{scheme}://{user}{pass}{netloc}{path}' + if stats and stats.languages: + c.no_data = False is c.db_repo.enable_statistics + lang_stats_d = json.loads(stats.languages) - uri_tmpl = config.get('clone_uri', default_clone_uri) - uri_tmpl = uri_tmpl.replace('{', '%(').replace('}', ')s') - decoded_path = safe_unicode(urllib.unquote(parsed_url.path)) - uri_dict = { - 'user': urllib.quote(username), - 'pass': password, - 'scheme': parsed_url.scheme, - 'netloc': parsed_url.netloc, - 'path': urllib.quote(safe_str(decoded_path)) - } + lang_stats = ((x, {"count": y, + "desc": LANGUAGES_EXTENSIONS_MAP.get(x)}) + for x, y in lang_stats_d.items()) + + c.trending_languages = json.dumps( + sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10] + ) + else: + c.no_data = True + c.trending_languages = json.dumps({}) + + c.enable_downloads = c.db_repo.enable_downloads + c.readme_data, c.readme_file = \ + self.__get_readme_data(c.db_repo) + return render('summary/summary.html') - uri = (uri_tmpl % uri_dict) - # generate another clone url by id - uri_dict.update( - {'path': decoded_path.replace(repo_name, '_%s' % c.dbrepo.repo_id)} - ) - uri_id = uri_tmpl % uri_dict + @LoginRequired() + @NotAnonymous() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + @jsonify + def repo_size(self, repo_name): + if request.is_xhr: + return c.db_repo._repo_size() + else: + raise HTTPBadRequest() - c.clone_repo_url = uri - c.clone_repo_url_id = uri_id + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + def statistics(self, repo_name): + if c.db_repo.enable_statistics: + c.show_stats = True + c.no_data_msg = _('No data loaded yet') + else: + c.show_stats = False + c.no_data_msg = _('Statistics are disabled for this repository') td = date.today() + timedelta(days=1) td_1m = td - timedelta(days=calendar.mdays[td.month]) @@ -176,27 +212,14 @@ class SummaryController(BaseRepoControll ts_min_m = mktime(td_1m.timetuple()) ts_min_y = mktime(td_1y.timetuple()) ts_max_y = mktime(td.timetuple()) - - if dbrepo.enable_statistics: - c.show_stats = True - c.no_data_msg = _('No data loaded yet') - recurse_limit = 500 # don't recurse more than 500 times when parsing - run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, - ts_max_y, recurse_limit) - else: - c.show_stats = False - c.no_data_msg = _('Statistics are disabled for this repository') c.ts_min = ts_min_m c.ts_max = ts_max_y stats = self.sa.query(Statistics)\ - .filter(Statistics.repository == dbrepo)\ + .filter(Statistics.repository == c.db_repo)\ .scalar() - - c.stats_percentage = 0 - if stats and stats.languages: - c.no_data = False is dbrepo.enable_statistics + c.no_data = False is c.db_repo.enable_statistics lang_stats_d = json.loads(stats.languages) c.commit_data = stats.commit_activity c.overview_data = stats.commit_activity_combined @@ -209,8 +232,8 @@ class SummaryController(BaseRepoControll sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10] ) last_rev = stats.stat_on_revision + 1 - c.repo_last_rev = c.rhodecode_repo.count()\ - if c.rhodecode_repo.revisions else 0 + c.repo_last_rev = c.db_repo_scm_instance.count()\ + if c.db_repo_scm_instance.revisions else 0 if last_rev == 0 or c.repo_last_rev == 0: pass else: @@ -222,21 +245,7 @@ class SummaryController(BaseRepoControll c.trending_languages = json.dumps({}) c.no_data = True - c.enable_downloads = dbrepo.enable_downloads - if c.enable_downloads: - c.download_options = self._get_download_links(c.rhodecode_repo) - - c.readme_data, c.readme_file = \ - self.__get_readme_data(c.rhodecode_db_repo) - return render('summary/summary.html') - - @LoginRequired() - @NotAnonymous() - @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', - 'repository.admin') - @jsonify - def repo_size(self, repo_name): - if request.is_xhr: - return c.rhodecode_db_repo._repo_size() - else: - raise HTTPBadRequest() + recurse_limit = 500 # don't recurse more than 500 times when parsing + run_task(get_commits_stats, c.db_repo.repo_name, ts_min_y, + ts_max_y, recurse_limit) + return render('summary/statistics.html') diff --git a/rhodecode/controllers/tags.py b/kallithea/controllers/tags.py rename from rhodecode/controllers/tags.py rename to kallithea/controllers/tags.py --- a/rhodecode/controllers/tags.py +++ b/kallithea/controllers/tags.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.controllers.tags - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Tags controller for rhodecode - - :created_on: Apr 21, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,13 +11,28 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.controllers.tags +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Tags controller for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 21, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" + import logging from pylons import tmpl_context as c -from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator -from rhodecode.lib.base import BaseRepoController, render -from rhodecode.lib.compat import OrderedDict +from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from kallithea.lib.base import BaseRepoController, render +from kallithea.lib.compat import OrderedDict log = logging.getLogger(__name__) @@ -44,8 +48,8 @@ class TagsController(BaseRepoController) def index(self): c.repo_tags = OrderedDict() - tags = [(name, c.rhodecode_repo.get_changeset(hash_)) for \ - name, hash_ in c.rhodecode_repo.tags.items()] + tags = [(name, c.db_repo_scm_instance.get_changeset(hash_)) for \ + name, hash_ in c.db_repo_scm_instance.tags.items()] ordered_tags = sorted(tags, key=lambda x: x[1].date, reverse=True) for name, cs_tag in ordered_tags: c.repo_tags[name] = cs_tag diff --git a/kallithea/i18n/de/LC_MESSAGES/kallithea.mo b/kallithea/i18n/de/LC_MESSAGES/kallithea.mo new file mode 100644 index 0000000000000000000000000000000000000000..cec049f74fd5b90e7420ca601233da343b6dc936 GIT binary patch literal 79776 zc%1Eh2b@$z^8a8s6!lD)(-U0*WtR*m_cM@L;=(SVBI28wx3j~}zFFtZ?6RvE5Cs$J z-++oDo?yN+fZ!d-iKwS1m~+4^`a3h`fd8uc)=RUq1pRsE-7Oz>>UHj}uCA`GuI^s5 z%T|{~=wGj`B9VOwt~xLh`gcnINMw70QwbhM@LYl=1Q!!*NAMkjod|9-0I(-P<>% zAHnGacPIEag1;rWhTu*FKP1?e;Ch0)5ZrZOB(f*LLk7bCsDX%AL9h)$Yar@Tt8gm8 z?YKVbzFgt;1a}~Kho)OT5amCj;jb(Fklzah9*!#^5?_I^+B0D?OY z2L8GZ242bsqufe@2Ej&xRRre@Mt)ljiA07G+@9bS1dkbl_I|2xn^M&G0D^lE>{5#M z3{n5l1h?k?Dn-4jN|A566z! z#_b2Ak$>kg2p>NN`J6ol?Z0^p>V4N3v~#7x*9q=T@CS{zXF1XxSPps` zP!9Z#EC>E4mV+*{<)EAM33gz7l_Q^J<-qgv<>=q{%Q5cOm!teP6)0z)3iuyffpWSK z+=|C<1@b*g{Re6MvI>l^V+kJ2^rHS3SAY(#(scJI{A&f;@eskTT#pLiWuLL2&!J;c zpD|<6p4eEl^W?D@x95%per_ELx_nsEtr?4Yy*n0k_=&o=9f$P0jsu?Bjl+02d>qOd zF%I}Rf#8t@9fGCYALD?(@5h1f6pbey!uS}EaWj29>UZaOwEL0q7@r@FSAMMSU5^3& z4>|_%k30tT8%L0`j--!4{tq34`aY@fjG+=t*U$02>maaxb#&`;wCb|E-D0hzu=%-E-5MDX~<6^=D#5+&n6&ioR1l02{6VT7kDg26HlIj0= z(9<-62N9fiJjUe%3jgQEkBJlgxMAUQZ6Oezq z6F`?opMdsdPQds*^911GR)tGX03AJg0_guWb$@mO#?NmiA>J;N;NNZ%;`N#YJeE#E zzmJ{-IzE09%Fj#!9xl@Kw<%nv@m5VjzrCsX{$mpA`Qs$ubEgwQKl`1CbnQ<>eR`jW zaoqnzw13EnNMB8mNGx(1!6OL1a3b)zy9xaKkBRb5FhPe26ZzRD%4;++u4b6P<6IN< zS*rf4)cux;_J3}oovov&Ur`k8>Phf-1cybD|MV!*Ulc|98>1-io+#+)K~49(hJP4E zJ=aG;->qYC9}q+Q4l$J1N8!*I#?5gt%mY<1)bA344Fqq90bfQO_$-PeUFSH;Jxcw@ z#*zP|INE|-_>+mCIEL!U_7-? zAbfB_<+TL*C8z%9Copf`oIrW6B{0snt%CpIRT!^ng_l$T-%F}6F5j%e_}VUsd9`~I z^_oPmJHZQ*2w$Q8?i>|s zU(Wz9?_{)I1ZQx)GHB;i2Y8z0Apdy|;{DM9-WEEbvf>7-_)ZX?dpN2&h?1byB_IB)g%9S zJ?8nkddR~o2=*oTU_I*9dJ5XH_Y}0#n1X)nItBPVVhZpwWD5Fk%oOz3i5i|(|Hdi6 z?@SH9Sl#ocpxrlXzJHy9`aP=YU)Om5m;$-!^C{?$?hW8GziU804rx&NUfpH`+F#Xx z_U9Tv?^6|C+JJiB+JN%!ZUFusB}h|i6plI>?K%6bwOHT%#9@6kr}X0(=fR1$e1A1@*2x1?@TI6y$fVy01C~<=u1&>c8X^(EkIcp!_wO z{$q{5^;DFz>r|xMcPjYaVFdSQI-QDkR8PhHUpE!$&Yg<-T%qB&Oa-0Yt@%7W74?2z z^M7k9`s;(KsK=J4B7NIa5&w`=QO};IqJE=J1wXPh-sz_z{r^+<&8GryOHV~R?>iOs zT1~JQ!Iw`(zwUAx%G>)igdawbmU@xH36?P(pN4ts#nVvkH>Y8~*zt7adj!G%Avly^ z4}vpJNB=K79r=HDI_mT7>1gNnXJFj!b_T{<*E6sV?R^Hq&p!k0z3dE>H~$Ra^)Ceb z5Pa+mv~$~Oz^gG$>#gp?r=h$7(}3S`(}1VwG~_>Z8tC`zY2XucreU64sPSH%2LAK) zG>osq&jg=1`b@Z|or!jxb0*5USl!nvy!A}rW#O6Vulvq~JopkpT6#vhPX`^GJss(< zRQIjZk$(Af)cc|7$mgl)p!?UR1211IY<(8;-~BAmW0$j#-{`Y|kJwpAf6`ePFQ=Y` zex7$01TsK&p#XaKYlj)=hd^(KkLp$ zKCNdU{Gb^acU@4IR2`~O_5H>~pjXP$@tz4bh-$5x*QynS{a@YDKy^uu1~qy8Pw zN4mb}qn+{dQQs*9hj6*)qn>LB4(4%tKIF)L7l2Of3lM(B1;EcW7XY94T!4B%qW)_y zK)zed0$(^_7Q!oLpA4E(Bi3T!?fh zU5Iwfyb$GFeIe36sqx+?NK;j0n~M7GW5f% zmjPcNUxs$Kz8w90;N`$akINx14Y?e8rQrlgG>M#iIq>rNPn37?XSYP=yVm@G2|-LJ9QPt<Hy3a5N;A)JQ zVOIm6ldncSW?l_EUw$>(eaF?n=OYT=y&C*y%WDv?=o-}LsB6&fN!K8J`ZdV^hHH@j zgV%sw-ns_uXge2h-??b-!E@0+9p{1$y3Yk29yJ$u=&$jH&P92n=0eYqo(ufHKNobi z!?oaJ2VV>MKXonQFS!=-@AKCJ554B0{-fuioz?TupVQ|de4fIk^N{az3O}3&{B3m| z`1Ib_q1_eNLI2Wl9s2#Q>p)-cUx)m6`UBQ~9sdA4T=WNwuN4IE;PFdvJi+U(hrIR8 z^=N(BUzyjd?m<6hz(Re3mc;f=})2s!k$5jh34*#h6JhuS!@{a|et8H#T zy4`O8o)5hN^2eYXfX})cKriR3`_>zf|B4&XkE?G$f9!c9(s#cR`Hxa}>PDoWd86`y z844`s?sp(0@k|Jc;0h zTTrjnx1c}XxCQNg?-tP2*0*9D?SCue*h2`?5;u~#75Tk(EAo5mR+Q7~Hqc$`+aQPc zx()Pp-ffsa{(Kwcldo>W{!8~iqMW)v!hIpZ0R*4=Blyf7e?q$c3eWfx@cq|6p?}x? z33A#&w?pqg;dbC<=IxL#|9Cs{f8lnFn@?{CAMS7m(v7?W{d)Etpu+`sfWIsuIGo^% z1V?kb?*yGsxfA^|?M~47)psJlWp|>#-@Fre-~KM(@xZ%4FGt=5{}Fcq-%)kf-G%y| zr~Y@S`+>Va*Y7L*>MqoC>xF;^FGTwO3z7dZ>P{>~Kb*1<{WEPL=<)1@y1rNlI=f!o zw`=$cO}AFVjRD*5dHCy`tQ96>Dn!VyLb`G>$wQ?^x=z;Pw67vhgt+W zJ$4cJ$SIocj76Z2bJV>=;a@fXzb(>ri^A6yp`ITsLOVWN1pKU5xc%KIckjEA&w+O% zUB|n@KYHB_elqE963y{s%1vUOFyDx?=S|YBACeTnxGzxfpbP%wp8%{Kdf2m5Y)8T!JLlMQ+ygw`qBI zseAciwCjPzs^?s+dJoO#%f-OUcM7*yf^xQ9f_m+~1o?DWf_jxG?7al_J9-Jy4PAo# zMlXR}I8M`FvIO(f0*${${oh-H`hQDsGSlxpM3V$-??L_7-Gh4mcn`|o@z1FLZhzK! z`_Jgtj(B3_{Je!CQOx!+RoozkVCvnfl#59TO*cqzv97fZos_E-k~d)zYQ zbJ8-5pVJjywhZ{ZWf}O#y&C_yWxAiS4DDLKO!0Ux;O_ULT?eVVv%>$m7wss$7wN{| zi~OP*-k|X8d%<5Wxfl5Vqxvtt7kFB!?x!{U^?SiL-oF?1`a#S8?Q-zty_bUz{cgGL zhb%`uCM`!jYLZ(u|W z`%$l1_oLm{-jDh$)bva5S30{N^UfC<-&l$Kx~>FW4qA!%BB}ltu0;OxSE7CkS7Lqe z=arzlk5{4}w|M|~I^+SwJMsba(|`xi{xJ`rzHxQeJOI9P+5;FzXKMVJ4}cyne*pW@ z3m<^J#=#H5USs8hu-6#>5bFQQL$KFq^*79K6aJ=r@^6^OZ~Ghg)_Z?LyZ3zdKmiX{T~57CO(4kdpbdr^Lqs4{PyqA&;9Q2Nay?=^}YV@m@nEs z3j2QxoLSr@hqtj~S+jTX{|J`bg zt9}Z{u7(^?wHo&M}4_c+pbdK`HA{o|158IPl%FDK{_ zeD-nRuk;Dsw|@fm8fQL%ar68WsNYskqTTyGiGJ++B=Q@r?#d^D|GFo!F1z?i^yA%6 z!d~NrCsEJNPbr^J*#9Z;uMtlHZ|SFyU)@uX|IdC3@$kbXLQ_Z_`+u}E*{i)Untz-S;XJ*S=963XVK3`D>R>ly~ea>(Qh9-3p}=Y4t%LZ zVa0Rc`;E_GykGSk@V??X^y4efp`W&X9{4}>dByMZsAu|l(k%?FF?ncmaI1=L?|!Qgt8y0>(|P#yds*&)0bKUQj;#g6{vk06Ko?1(g5F3&6v- zntt~e0S|dm_myA7_!|Bq@*Vpk>Y02|?I+YdL(^TM{x`j-c7ZRV{Yy1`&5O{_fAk{O zD}!GGKF@kd^{OwSywwVydkO7(?Iq;;Hf9NZqr{1q1U8#modPVX6itc;8g8H7T@h^D= zR$e+7D!onHmtJMUH9zk3zwu6h;a-lG2Zy^8$*{wmu4%B!H; zZ(c=x_g;hfr2QJ;f6^M1Ypp@Jvqt5ZHOOa%y02V=eweog{ru1x;O(U~ppUQDKz?ca z8sbfT4deCt*HFK^Ucd)juLIw`URU~m9p#^|aPI3EPj_he6R)cr z`8xV#{p-NnZf{`zKl%;iTlWUW`8@T1;th<~-@FNU=$n{_N4|-1dG4DSUkl&Fy!!H+ zm>*idg?YN?TL@3S1^i@!8^y6!5F+M(73p{Qn5)&ixeidi_(hW8J6dhi^Vbd$;)v z_}J?+;O*eg(0|3BA>Qvbe5m@5)p#)tPpSLl&(QAapMgHE`V95E;WN~Gsm5FR8RVu_ zpP@gtTL(U~(>nB{u@3ENukORwq5Vg%Lp~$cfuD?3m|6!qKXV<*zhE8kcl|o(s~=eh zxv|6Npo6NEq!Y98_dkGEySo8hy3*cd!FOhzSFENiE@}=7Me+hh!{t|eZ_$BI{{u2Fh z)|bfd5_MnyCHm#gFV&9WOSF6SmufGo>A%+azx@hu->)DC9r_jc-srEOhs%7WdbO{R z&-EJrUiE+UE7b4RuOKhI|CQ=3z6RXyYqX=&*XXaFU!xwwzt;9>y!6-L2d93m^ZVCo zH~uxo!SkAaou+H^4d{8_Z{TkC4eHh78|Xp%eFOSw_y*;j{td>##os`WKmQxpYpnYQ z^VWcGQEvQO%omN{svPt!^tE??3%dFCTj)(Yf2aFN-=X~J-=UqCe~0>BtL~-WK~MaE zy7&4X?QQox%Io?)`1j!NQO<<#(GT;!SN-7kXxCHUqdl*GkMh>4`y0(C@`LKne}KGp zzz?WLzaPLqPxt}&ocROz&-Fhb{o6l)Py9pO#p}_o9_vxg|EPPU!g1??mlM{59;(+v z9z1J3>^0V`M|-;di1Y)0)P0s8k$&=zpqI>#$mi4_LHFnVsP-!g|MDZ|`zL->`RGU8 ze~YvdeDoy9>H8Dp@lr-m)?EZyZa9-5%Re^~WIQ}bkmZaw2r?b*+^Ut}r9&&kA48Dk zle$*O_d0@Hk3SLQ_B=q4$HNP)Q2tj0dE9NiMJwp@2+FyIEl`gx1i2sk66AiVBFODL zX$$0gEmWxs)K|`4)n5UTI5| z|In7G-}76d{Ivv`o<7+U?fGs?)NjYFT1mh3BFO9NBe#No%~rtMrCR|XcM#-paW6q0 z=l{@nJ8ccT_1+rsqg$h1rz*UZAj@yJY>obSSK(H_L4Df&2JI^*$o3jJf;>;YNs#Gy z$JXfIZmm&nMQh-#p*7k)t2Np=k0A5?J6a>%bFESSH|pMTn^rQpyf-KjK-41v-XFJ6E6G67uSgrAf zY!CW4Ug6~JK@U^5NBBA0gRZX8@Fm-WJ{}~<_8O0E4?5ay2ZSH61KhCdF4!66EZQ0UuykkCWA)Bx_d7eIpMTsL_}FEaRw6GQvJ2?{ zP=ai)aqKQ=*HgP7{p$o-@A3667@r+?1>KeGiuNA4E6N+TE7~z}SCp6C744a|E7D)3 z?nf0qzbo4J)~*;2pKE?UYWnTlg02o}3w|}AE$GH>i}ucL3p%_(!&kP&`1r6b@Vmus zsL%GhVZ0u+8|pc9H;k9#39>vhZ8!A8J-dNUpWY4me6Snnu+{FM&jWV{zdT}h)Z5%0 z^q3*Y^X_bdtQUQ3ca-0D5430hJ%G={6dt|@@IQDD;B&$r=(iL1K)#7Rz?Y`%f$~q+ z`1AGvzg)Bj@b{NJFfJa_bl+;c?e;`_4%icXpwFHdFJ*fIpXohOj|(*3oIQc>#d~7h zKCvh8`stqFKfm1z;a&DZeTMFZaX)!4gkQTC@?WtR@_&6V^!NI`(2mY~1NPnp0=+8&?Mf=}T7}*c`?xV2VerR_oLEi6(?FW8&J3-!OdU-$e z`~LfbzQ*p4a!w)0>%Xh^2Oe4-fbrFhAlqx02cUkt7~p@C4YdCX1O0oo0lfafKs_EX zFm7KqK=&VM{2vUAhgJu|edvL}YY9P?^L}?A=zPY37_Wak5d7}m1Cj4T3ST`Cc>nxB zjF0a$-VW_RPrJ86KONc*_2|_O<(9U?ILQ!X`E^D+(82AR?y+{j^PBB}ul4Ofk9`k9 zyzvLYU3U=jKc674Sx!261W z!B;*z82sUfgTc?*7omPf6`}s+MZiN<5yDR^LVmN0P><`2(C^EOfS3O*!nj^ng#L>h z0(_Jlf^x4nh3w+M}Gd?a{v-+oQiaw+Fp+C&>01quZliE8C+#o^OwKuW1ju z{jNR6QQHo!M2_8;Alqw9?1229?Erb>#SS`;bp+iVK#=9|ksVRr>pNopc(Nnn?|5h{ z*}oljDB8JL-ER_Pee#IIT8W-_$ze$MzQXpMfN!f44r>V|&W zwHy48>V|ZKyMf-ubVGR)x?$W;QvbBVDVqKaP4`F5=bmn$kNed9k-{%E-uiB!`)#`e z?%o~sJg7U`(XqR(PZaj=j{1-8j(m>MbSHMlc&X_Qesa0ybF+ru-W~jOS$EL=Tit=r z@729?59D`f58$I)52PE=1N9u;1NAvx-Bmr1ztaPFY0z|2)&IgCz{_PlKv#2nfPQb% zd|%Oc?`ysv6J&dh@6><2`ft?}?wxun-|PwcJG3X}=c6@zbWh-AyuuTDq8zIy>Xp%W z(|e*`=PJCUC)#s$Pt^0qo|q@^>iQd%=H5FQh-N7siuCknJ^| z=!N>1_f~r8jq=mI!C!N|fw$?s(XTUmBj3vjMhw%A8%2&$lg?O?q7FI7%5-#$Sh}Xh zva?p)NZUrN%Cr-fV`U99YZP^;ud?ipPBU?9bE%Y(u};caPBYOtZZd6C^oDeDF+F3`cmQ7RMb;gl83{+TxnTx{_I;ZYJ}(LmrhsLn3-yc)GuS&u_{Zx z`%A~C(h1)|R1k6?Ub?2%Wb&cUjAdq%c7p0xn|6}fbf$s52PIRMF(6r4={W|*lUdK< zB;!_bw4s=x5f4Ojybq&qJnlONSSc$j1rAE5Qfc6U9omXA?y)gmk2UcVk1^%t9uCHM z)in~Cbgq^<%c+W{%}n7?YB{%3vMDG0#;W8iOKo?u$r$`|HH1}ZeuassW+E*BL(X;O zvQ_Df|0OX)gUaOC-Y6_-5+0(@c12D*H%2n6F@OO|fco%963DG&{3GwU>vr-zT(?nA zV~Z=3v}v^PF!mY~=N@5?CYfw%B5)vY^qb*kRi-lmnlcoNg+{9)O3)NYk#r0@O@rU8 zt)<*4dOT{>TA3=dmTH!zoT$P~yo@j|$~J50voe#eF^Hd_Ne#qkYK+>HWjdCT$=MP@ z8K#mkliNXEY7!Ho|LIKJ%AitC%(VTADB1%R3(^uZp#mf(-kwK?B4%}|q-}K!f5%d3 z$BK816c-yKsi`I-t=cFqj&v0k)D@hktFo4!9=GXRR%%pR#GHgJOr}V-nZnQzpW0lM zT9_9QP3N+azA2HPRb=SmQh|lTzauK=TtF=kWY$dCrXUcN(qiJ zeN-|sE$*+Hq~mZ*?w+L3LY8Vk?HW>1QDzLxWGIUsU3&GA*7l9XtlF#@O<5(Vj}>8- zL4U-plBu{cn9(ZkkwhiTN5tWe?L227!C1n-_Yv@?W*S7oVD#caBvwUH+=+nwXc}{& zP?0!<#A?!YmdD5$RoNd6TwIsRO2UpM3`X!3>6;*=r&9dq&u{D~Ei=q`oQ9}F z+0YEe9ZHi)TmsD)cvX!_lTz9SssacVl8jOsB0Qo~B0O%2RcB=yNW5VtkdH!&AGa#a zTq?_)N2r?%pu8}Zd{O4HDjMK+AaN(=X;f|%$udlgv7D17hSjtbE+jvH z$18yNMs{^?|k`XLlMU5g}beb4`qkO6N$LHNks@4F_Y^n0C%gH5-j&VMaJ{ zR~i9H_BUOOBpYSWTB*3h6$zk%m;)hR_-;BD%Vk*Tj^`wo7| zn@m$I83n$L4n@8Uy51%ZN8Oz_7)#s;T(UQ_)KZh{X}uE;%q!XrWo3dY z53nu`O02$$!TT~QX|4)5t4zmNt@z%Iq)MtyJm42tl)6Jh5Kz+j6^F=RU|kq)hAxL)fwzB^#ck($aXpCwWWB*Wl2%g4$jL>e zvk;jpP$?@DW=9U{Nd7G9I79+5qQ6Sw79@yBT&ad_MPxBX!$HL=a*LRTvEp)y{rMI0uxoq5x;l{@-J1(>w@{e0h1HjlzjAPR|qlP3OX1heR!R2dk zB~R_J+_^*ND)zBtxj~KR)(NxGPvS1#SBk%g8bsa58UtbMSOrd&)k;Uih%4~dDeU$p zcenSL8_PlyBtV0Sq*~j{j5GEMp-ze>X+>pwS#fVh`lnMVvsNjTTs1W&HHvn_ zSS^;Zu3JP6+h9$IadOwGC9c1hK)5htHs?TgF`Ncsx>G#$l#{EiB~n33;>;tUCU%`# zJJ(qg4ppZFi!M}QK)LGqcs;8gW2hkz^<5uk{vn53$pW5bGPlTV=>}$+Wa#;HGNM{M zeYsU*a><$rr^JiTF3+K8wkwmF8YtyGj<24~GBByh_!!KK_-4XHFa{4U96`j;4Mh-6 z!4bTk3r-=MohE5DTT-%iL-hz!W^-};nr$d2e?hUaSoz_eXkrCrW?72`qcNXr220Wk zrR~t#fpzi0h^np<+1SRssk-i_k)*yRB-{Kd>-u~HF~FC@^{s7CAxbBT-~t(;zHB67 z1Ghv|4X)LNURE%nIq$WP8K%6^H>hh#u~;4Ah|^KdfTHUjB}R>xZF_Zysxj zK>RSx!q2B2*DLNqgC|b?45`iw`=ZT-LxJ=_7%_-GLAO*R-yKdRb8ms|q5euyK39QW zM&$Cy0B;}0`%;D90Fp4VWGmrsD>6V8Ikc+wbcrIOu(C&VEMAmg-@AS;kCY@(w6cD& zlP3)k%jCtDk)>6TyM9dCachdmYrK4@v5bUeyDQ4g$+(_c>r@3Y@=|Yj-RH*2*BTi# z3^T&GH3qj+_RIhvJGtMo))-KbZ#Cns`i}v5{HcjYC>~U@fx_ZC8wn}7Ub6b5h+&Pf z8_MG$7&}bZ;wzG=pjo9`S=AXLdQmT+ND?N^xYsq5kXDGvTJ1ODYc`g9Aw)RYOuE5H zr+6zj%T?mFn%5v*xCNR>OFCNN@_NOeM|l&JncNt!WOpGvAZ@qj1rG5~66M_0)luXR zD)ByK^UIOudUCpBj4|s&?#5)T?-m))b%ht;LX}NA-HYn2(+6@}q2=S&hd1PcirW~; z?zX%5P@N2x&LYlR@eM?_n-OVQ_No!VG)M%?S%o6f;xCaGJMQxt zUQC&)bwwcKoVT5MEe#*1iWjdbGinjBh;}mO&Y(f@Q}}0Ic$hIF5L#(jqXs=PRxDYY zl*Q7(!U}s?Bs88)8E6&^M*=0ZjRo|K`Qpyj(q@aRaeM`xG$J@C+$7 zl7?7yj#gJreyS z%w&vDi$=wh0L;9-A|vSwRWxg6k_ijjuwWUSYe>+JHn`>ySgc#|PRN~G>2P02FgINn z&XgjacC&Q2;+aI+Utf_(sXn5q4|`Y352R2cfvDvd!@Em?%?ydBSfj6WC17Zc8uk(X zB3{ym0mGX?vd~tLZ|3E=$>^6?sHJ6*L3zut$l%fns#g{tD%eB@%Tg>A5vh@XLbESV zvf`OaR?>Vy?GP8M-Id2UNjoOn8HNxU8@NE)D=|c0An0>dClFm(vs~1Hsk&oOxaEbs z)(V9>^cz%6L^|n)L zv9;h?L^h?IpHTgcqi zVZeHo25JX}pTrXOk5AkGR0cN~N;R=HG{f8FlvS!GGQ=WsXXZ47*Dd^0Xs3;W)08#; z$by5uSg$3&!nLE)yE12IX*NhOPSx~`H$|)r?+mkD8Sh~b7pM{@OpM*=ECun>%W9CU z-1KD)*(%mIjOknHY?=V_imvVEdVaZxCy0jyuWz2Ph3tsZ^ZSzWFEK`;yY?_?m zZ8)_wnj@t(yn6!t=B+=Dij-1A*k;xYS&^BJYX+hER$oM5cIxepqtAGcDXZFtC}$S) z_bheY$-8|b14Ny)=%GZbKlHH+JQxEzM#SE z*0ny~*iaZNyHIA7Yr^RgIa)T7REDj*Y+-9d>XCZ0!O62a%-Jm72xU-Cn^3YPYD`w( z^e;7laHo^(8QKjxJ1|zXCOmVvwrjMujq?-(o!2V9C>j^NU|14&iIrV~phJBo>ryA1H6x*M;Z z4BiHXgc=Ou`Jsc;v9nWWAEw{3PwQsDTD~T^s?wLnHA{LG)Ga6F(pi`&mw2%P%NXG* zrT!)j)LO1iIwUKVZeS~?G@#Lr3{^WQpZ|$5ECppuHcs;W1IvBi)0K{fSyrtKF;Ow_ zxDaz-Vp1eKW}%}qjWGlJ4j3^Isxq!Nt2DxD4B{cftOouw+?4_3Q)U#pi%esYd#w{l z)uCCRwcj$mWehuqJ%7pp>V2tEEJwsKTofO}O)RNB<=JqPvV}nezK5r2X@E~*>GCxu z6x}@zk%2Sir>IHO0w_s*j$JmAXL+~T-SHjn3W&qCIWcH@Wf4NbB;j%OSfF&j1z+4- z0Z)9YS(f_&!vhhDQYIU%ix?~2AtB6%)i{U>0I8FhOUbL{Cn!U*o0}mZ9FQgZYt{ye$8R(%AR@N-8FcZAOjf@~#6H~qsdj0`&rF-r~ zS10}!3x>HGvX^W)mGoA@R1JKB0^QSKsP>t@MyB;d1}fj+FWZ=Dk=yiB1+`A>)Ll>* zNV7-KV0whAwIecO`G={y9F{|b&@mP-4iL~}Cqs>+Vjf|MD_I-L(3>HG4z4BdWt(0JA!Q(YNDtuTV#bX&#osB6j7;nC zH~Mge!3HZUPTyQx8%t6l$>!i;;Ru3(ykM8B`JaT4EOa!!AKRIQTyF8II^s_eu6TXR zXE_n72g_WitI&489q&WdFU0PYpN(Ymsw|tOs2QK@;q9%655|?7yB#D=7>8*{z!-o8 zjiimH1y|MT?Iy?wv1#EY@ChiTJa4-g7?Hh&BxnwgpGy$ehc4WJlap*x@9s98C+Hl1XHeah4n_ zS#T#WcZV}6I=6beWaHV@n3|h^I&u>;%%%wkbyl9pGm7mj^H2E}_LZ5z-9QWy=_s5Q zj5ZK;kV6TdCAtaDL=jPixx+Xucrw7#Gm1P&z3U}LF*Hr6kk5LzrV|NEzJ8*HpOA_w zPwTa0Xp?!AyKT=O^(+|sD=JR|J&NsfBV}yP#^PaQ->Oy|rG|ihMFs0O?9cIyPQX;*y z9@b==?K1v_mb%O$dU7q;B7sfdvfzlfnbnmACZoVN#)Qvz%Sh}Z+Nz-s8KjnO>Onxv z^Yqw#ob=6to9y|zY^@Uh0Y~RK-y69X2v!$DHh)c7A zUjzfLv>wN+wV3m8t4Z=m@|j6f4i}0Ud5UKFv@DvK^7FIg)~1;+TkgJ&6Y!x`WdgmJ zNsA>w(7r41?Svd*>>$8h&y|IbxrCi)Q z!Oiz@k8DRpVUOeH&BZAY>YfuA&>D{|QUW{g$IKe)ET-_Z1YY*#>*4hSEllmn2#-O^1gl7#tPSinvIiD`#6!nOmnje_ZVdE{p+n;82lLeMfJac=g#qmi zOzT{Ke+l9T2Gm1tv_c#8p|xAk0i!9E7xheAfp9y$fj~Jw)qF67nL^=tGjb@*(-Ve# zy>Sup%|AlNd(_P8nc<7=_wQBp3-j_&TDglR;~#x099pk(iyzt$_~cCo#(LB31{R-UNn3b5Sh2nHUB3GMhvS_lJ6he9DuJp*9qz)CS-DiB~E*MYH0qNt7V*G;Fw~ zO#;DFK+u7uCNrj{CbESxDuAr~u%BIqq)%*M=y~UO3wRa8gBw<$_D!mh*Z@CqLkn;d zH>e;l@vlXomWi&p*#TD|Q8PG5G$A$DKCv0D)F5XNX>{6oM5`z2QqaN%0^kGbDCjRu za9iM-h3KAJUbMI$ula@+#OFqaUo(h?B}q7H2<;o(Tn#1)qdj~ROkFH+UfT5or)?SH!^Qkz^e3Qf{(T7vX^r5m9VU6W%eNZhI#WN z_7ZEg|9Kfa#yc~rW~T5Et!kMsFE#N~5f54-SElqfD7*t;(#v&DNB1%kV3oJl#HcTH z0x$z3oxn-g@)5dIjW17rgNs&u_|n~S`DSwv>J8sfF}&P!WMtwfr&8p{z4QwXPZ?3p z<`<@Hi@1Akvh|bA#0Y(TmGF-=I)x>z7t!d=z;M%lI#2Y ze2b8OvN?#fi#}YtF%isMJpLcpM*LL6h@VlkbPat}=7QUm;7LC-+hlyIQ92-OQraos zAcD2cOh=$Cwg*oVJ;UY;02j#d&YbI!wEeH9+pK<2A#Ykp)Og>7&zSJba;WzF^Qr2Q zXL=yKJG6Q0&c)ugmI(5jnA)9gH$8D+<9Q=R^T|Q%#y2_iR^){59MN&!Nf@bnSB`&i zlE3mO(cHnb?P_w`arp@!bQ2#eZnCCR?Ol^0{%XDDJED<2f zrDs@ArZ@XQW8hwu5EvKbu9*Ty7ZpnW{R(+kPak%oa$~8S?DVo7LTy29 z6xBI&;2~M*pMZ&Y7jC#8`SM0NZ-RHyE;dtPWp1!f-7}4ppk98AzHFN7sHYzUh$BUCgHY`$hEvpmGA2zbZ!XN?K%@9b z0s|2zXtu^4dLMwEa%tk@cwVMal}osHdL$E7SzH0(ux%e(h`72T86Zd|ws%$3`K-cp z>B{yt#{9w8WVfv{P4aApaLf0}l-ht}YhCDKk(Dmppq9K*6Y>@5V1TkAH?r)#bG33flB*rU znJC@xZ$5?`hAkNEFF|s$`>JZ-cv_EC%6hRddFbW2<+zk1QeJOTOK1s7`BV@uhLvck zU73zlmJ&vq zz`i@4v#@2G;%!pa8OpUOC7P99^%KeqCL9%h9+oXOLUKvBoKx|v$@#YGq@D%h9eTdi z1@{`emZC&aG)ht!&R*rEcwQsZpPdd|Wx`ex;UL{DZW`ildNmi|TD^qAytA}TgJ9S~ z-X%hdp`diZy2-@c)LVA*eP1C2y=g!$*wqzGiBaa?M64GGNGxIsavIkv4(>PO#vZ5? zc-pcNNymwM0a@^B6!%z*H-_9x>zYaE_37vpXXE30CeN&al2oB(vZx4l%RVl+D#73o{jYHX9zh(zE#u zuC9qy9gcKU6YFtLM;KK8>E>sCbYH6vRUb1YupW|G>&=GHEmSg8MV}^H+}xd?LeW7Yu6W=`sC# ztvNecn#qN${?)NAQ>Ae3bSMqU0l9`gs%>II-ra0sD(ZR$wpz)LiBCaravkexcioRr zAPhytjzPa6f8+W#^$J?ldeXVkp~^j=+fgGbJ-Vx1*R$YpTsII#|E?=&RO|0m|K6x*Kk>zfx=5Iv=Vum)O#x_-z1^xW3lz?Y&uO#3d+TsYB zfd{_xwL212a1(Z{d&}2YR{`&SxJ_+l)1|p+Nhfdvpcg3^C(LHOC^a&d5PiPPK5;SRPA;h->nu> z8AZnN29K|tThjJN~0N=j<13}k}IKrfgMMCs(Nhk(&!)=!gXvlMvB zD)@$g#CL`GD2~y3Q3b7H>YCvdx?Zgq^I8^4$Cp#9im@OP1ChN`4A_Vh)pUtODqw~L zO;}QHbavmMIyQJqbl}#DaDYq=^=4A9>hn*IMH|ALB%I8@ry*|w4af4{=zzE$*Y1JL z8Zs%Cbj(712In$UHd^$8J)PFEq1!Wp*6t=A8Y>t>0=@cn3NvkQ)##}5NH{Jw!H)G# zZf$%Kwn^)+$b=Diifv+K0`^fRHaT)ZA?`y{6PwIV1;RbH6+YE4!B>WcE?b)jIuFIf zZs5d?dAbMj0)fK4!cHBc6TqCqnW|PI&r{Vq?C&nH^3GL6Cg5JsaKhRq*1H87he#7~ zBzFQYnb^hAA`_f^4SP6$C!3astC|Vcq0o#cFcWerW^ivjv8RaX?;0`}#wu91KO<2y z?%Lu zI>i+_5$qw#b4Z~_)x@EOrx7R~^az|6*9k>-g0cC;GM})j1FTl7F((o{;w0u0j62-> zqv|Q9Hm4+#Y&KqEd7=SsO_O&QrVh!P7#4CMYH?X}-68%5iMLjdvfs+_l4t zf{2~Y6B-K6?}b|U?LxitgAg57MkkwS zqji*&7`iVced7e4R?G6!0-+p4GoPraH7kBAqbUnOJm){k4>CvSNMJ#qLI70Ed z6?g4!bnVfndym7q(7!f(vqEu&7MjlVA(UrgBr4?^iETU8N#lRuadfSmWGRl4?8&zp z9Z4zeM2G>0=D0@l1kG2WEbKI(M$GuP>3dBrB~coS<_p(BX8h?d&0;b4oMm z9Je}mY*UuXWz1CZAd;1xK89T@PUnbjzc=uCL;%*PPhXtXHntxxeO5`tMFzlj)Q%?`lNPUsibC?vuk8ij;ps$_4Q>W`FZlA8QMq!N$STIl%PT7hlO&z8DGVaJ z5BgT))wo~VgT7R)y2y~E-I$|RBrN;C>0RHE7A47VPm?oXoA9#laYWp~zPCL}sS04W zpG7p)$a@!g=nlSnDNEM@G*AYP2wY(=*Xd(yHd0yPoDvr2mHnxY0y7pe249<)pPm0Y zut&>3;dNmAZ2J4a#64uJShg^XqyUF_P=M0nIhuf^qE(qJ5W~#J*0DI*V)t>m#LD@0 zf_sG7S-}o!c{{k}?cjg=w}Z#8oL|LfDR^qe%bI%UAym}?)OyH8U`9$4I0kHO{1eA2GqS1CMsmsc#d4M|+bdl9 z<~}hT#9Dc+#cV;a#qK=jyIIBkw6})`7HpJJ?;*ns$#vWd6qUH*Ks!t8U|tn_t>A6m zmCK?eB4mhD+u)Cz@l>&o87wgL(=WbYUB$R!bDu3P(CqqP|I<_;=0ZuoZ_1^OQNBHp z#2uL%!gXto*XL0eC(QU;@*AN=#1?bwQ5#IM`Oh6wLYk^f4){f0JFaddagPv~ZF%oF z{NC|!!cU_N8M~Pmk7;n#Cu7wqqCKav-b#{0^G|*Ico;3RKzk%a=W1&$UCfy&hu3ei zI&PGw%o?$Hs!r3Y%#D?>z=TOcvP43Pn^@Wr$=PXM$B6YbbzjxW`Kj!G=A+0fr?YaI zI*{6*tO+lVH~V2^FEht6vyC2_E1`n=r#z87fRL3}je2T3Eu(2#TY0UhTCh?uqf|_+ z%H|b1$yrg%p1Me_NLBP@I6GIw!4mX8uplBC7SX)VymBp+ZijKpZ&xIabw(Lq-LduKFxtdLRa=AQ9 z0vJ#BV=T(r`mcFz*;NU(Jh)u&0o;Bp^JlDNl%()~_KVAw$=gYyY8b|95qa^A6*} zdsg{4D8N{anXsa)36q$tT(*tzl$9ZigH1^I@9_|GXp;gre=O~z!)JIyWcG`GCd{4aW^d0ZN&p#S?GY393Q)AfY3aeVlJ)?{|z zg=R~1;c`+e73Cf32DW0bWan|5yW_%EI7XGplit7LwdQez^p?k(TOMl;-u&9~SaZu` z&7sGdWw*G=h2nVgilzD}4bNo$gUy`C{>7hcmOBrj3Tt_@*|pwld9%6Y&E`#cvw7v! zc4FnSRF)*C4zNGyTi(C4w4=8kPu94%<7a=NSDVLrH4uX+)2?JYvl5o481ZUiAgU0W zl*LFlXD8IshD9gXtNha*c6M!j|7#w0#-+3VJI!n)WcgMj!MB}961wbP;nU7$+-iB( z`QPYWXHi=6bx&fOmY|u8gib$XOn5OvQTj&3piV4VL!r&R{hZ7uSP4ti_;2<6b6_7N z_y9EPSJ|MM`XR$yJed#^wWbe2htf+b-S2C82>Rzd1U*bpDM#EaF+-NqBT;_cD?>Hq zK<^j|7b{BjpZiKQ3Jq8!HuW*AOf{dZ+vt5_4N!)r~$IC%wy4H|&EN-gZmC!ez3 z!6(Zpe9XymHvW(`68a?s+uQP@^*{GTYu9>m(;u`RCwEKhvA-H)RQR~x&wJB4bj1OC zY{Cr(-V@h8lf<159|vPP zHykMiab#oB)T*+XsQ>=YZPOZ3mTI~$BtlOB6HMQMSAq35nY?YLfAQnndU;KzGM%Dn znGf@r{_){#xL<#b&v1u{+dUO5H+}>G50gi}Stura1vUb8 zYpdnG@Bf?kzJc-l4Y-y^zyI4F{U#0~+q-r^FK5}m*0;a;^k4A4JTX!TEZ9{sn|}w| zum2J7zR|R8i)Bz;R+ENzn{Lw}R|_qhj(S;1V@?!4W+tfa`PV%KKCqDTiC2bD83)eC zQH+&~D=Tg5zv^jlzL+}jGZk?3Qy9yf>7!JbQwAE17~p ztthj7<6GM($MrwlR_vzJqFV2>%DV^-_A#1eq;IY=k>QKNILi!WX=Un}6|o31*phCj z;yp&qL~dQwN6Y0dI=20=Q3GCA>@xn?o-typh%Y)%^-nh6 z_~+-mK_1lKl2iDY_mDxzTI-+l8o6vk1^0C_KEvkIH=Z40PEvW#l1D8u3FUodx#N%< z6Y%yHe@v3U!ner-cld^0hM;LXw47(2hLd1w%*wlWS#SGpbKfm*Vl5M7j?Lc@9NaN% zdCI)yDf55XQ|1GLwk8|d+V&nd4+_3;Sd9f=FK>DfG?=vMTjzo8xs654xwHMR=*e@p z&MmK={|CK#K8D3b5v2LXVZKr~VMZ^w%lN%wdjNUMw@w8F~$vKVT*P!ZPyU4qZN!<^RT5&7KGLL}`k)}m? zY%s65e{r<}MWwuVDt>-R1Nd$cN7s~k+DmWf=8b4RH_!U7s6|79!#44q^?&16+8OsX zvQDto-ojPgGN&I2+Hg3;LlX{fVL>jBEmgVn;%4N?ENa(~KxEnZ_%(Bt#6WVDR+FdR zfA;I`rBxaCK%cUz;Jt~#P*ICX3sm_^?XK+illWGQ@8rD+@k#I=>zc9dM`L(eWKy>=a9M4<~#uJu6!qk(iifT^SN>(QXtrqpb9?(@2Qu<**D|8 zS+Btd6aIwP;6;@nIO1j`?VtN1d~h6vD`!^w%he#lntvZY_shNyPs1sZ;?d#oQ@+#- zKlhP%NADai_)5Gx2m0^C=Z(1Fd-4AILnhFYNYpYjQRcmN%d_!CoBV8i&cBKSPc`%f zt^;>;`1~*u)We2WimvUys|5)>BrgxlPy!mP%|0gYAI<;QyeBV`665bUOE>#A{-S(n zzqFb2R, 2013 +msgid "" +msgstr "" +"Project-Id-Version: Kallithea\n" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" +"PO-Revision-Date: 2014-02-13 14:34+0000\n" +"Last-Translator: marcinkuzminski \n" +"Language-Team: German " +"(http://www.transifex.com/projects/p/Kallithea/language/de/)\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 0.9.6\n" + +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 +msgid "There are no changesets yet" +msgstr "" + +#: kallithea/controllers/changelog.py:186 +msgid "All Branches" +msgstr "Alle Branches" + +#: kallithea/controllers/changelog.py:189 +msgid "(closed)" +msgstr "" + +#: kallithea/controllers/changeset.py:87 +msgid "Show white space" +msgstr "" + +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 +msgid "Ignore white space" +msgstr "" + +#: kallithea/controllers/changeset.py:167 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 +#, python-format +msgid "Status change -> %s" +msgstr "" + +#: kallithea/controllers/changeset.py:386 +msgid "" +"Changing status on a changeset associated with a closed pull request is " +"not allowed" +msgstr "" + +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +msgid "Select changeset" +msgstr "" + +#: kallithea/controllers/error.py:72 +msgid "Home page" +msgstr "Startseite" + +#: kallithea/controllers/error.py:101 +msgid "The request could not be understood by the server due to malformed syntax." +msgstr "" +"Die Anfrage konnte vom Server nicht ausgewertet werden weil sie einen " +"Ungültigen Syntax nutzt" + +#: kallithea/controllers/error.py:104 +msgid "Unauthorized access to resource" +msgstr "Unauthorisierter Zugang zur Ressource" + +#: kallithea/controllers/error.py:106 +msgid "You don't have permission to view this page" +msgstr "Du hast keine Rechte um diese Seite zu betrachten" + +#: kallithea/controllers/error.py:108 +msgid "The resource could not be found" +msgstr "Die Ressource konnte nicht gefunden werden" + +#: kallithea/controllers/error.py:110 +msgid "" +"The server encountered an unexpected condition which prevented it from " +"fulfilling the request." +msgstr "" +"Aufgrund einer Unerwarteten Gegebenheit konnte der Server diese Anfrage " +"nicht vollenden" + +#: kallithea/controllers/feed.py:55 +#, python-format +msgid "Changes on %s repository" +msgstr "Änderungen im %s Repository" + +#: kallithea/controllers/feed.py:56 +#, python-format +msgid "%s %s feed" +msgstr "%s %s Feed" + +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 +msgid "Changeset was too big and was cut off..." +msgstr "" + +#: kallithea/controllers/feed.py:93 +#, python-format +msgid "%s committed on %s" +msgstr "" + +#: kallithea/controllers/files.py:92 +msgid "Click here to add new file" +msgstr "" + +#: kallithea/controllers/files.py:93 +#, python-format +msgid "There are no files yet. %s" +msgstr "" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 +#, python-format +msgid "This repository is has been locked by %s on %s" +msgstr "" + +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:346 +#, python-format +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "Während des Commitens trat ein Fehler auf" + +#: kallithea/controllers/files.py:373 +msgid "You can only edit files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:403 +msgid "No changes" +msgstr "Keine Änderungen" + +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 +#, python-format +msgid "Successfully committed to %s" +msgstr "Der Commit zu %s war erfolgreich" + +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:461 +msgid "No content" +msgstr "Kein Inhalt" + +#: kallithea/controllers/files.py:465 +msgid "No filename" +msgstr "Kein Dateiname" + +#: kallithea/controllers/files.py:490 +msgid "Location must be relative path and must not contain .. in path" +msgstr "" + +#: kallithea/controllers/files.py:524 +msgid "Downloads disabled" +msgstr "" + +#: kallithea/controllers/files.py:535 +#, python-format +msgid "Unknown revision %s" +msgstr "Unbekannte Revision %s" + +#: kallithea/controllers/files.py:537 +msgid "Empty repository" +msgstr "Leeres Repository" + +#: kallithea/controllers/files.py:539 +msgid "Unknown archive type" +msgstr "Unbekannter Archiv Typ" + +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 +msgid "Changesets" +msgstr "Änderungssätze" + +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 +msgid "Branches" +msgstr "Entwicklungszweige" + +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 +msgid "Tags" +msgstr "Tags" + +#: kallithea/controllers/forks.py:191 +#, python-format +msgid "An error occurred during repository forking %s" +msgstr "Währen des Forken des Repositorys trat ein Fehler auf: %s" + +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "Repositories" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 +msgid "public journal" +msgstr "Öffentliches Logbuch" + +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 +msgid "journal" +msgstr "Logbuch" + +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" +msgstr "" + +#: kallithea/controllers/login.py:237 +msgid "Your password reset link was sent" +msgstr "Ihr Passwort Zurücksetzen link wurde versendet" + +#: kallithea/controllers/login.py:257 +msgid "" +"Your password reset was successful, new password has been sent to your " +"email" +msgstr "" +"Das Zurücksetzen des Passworted war erfolgreich, ein neues Passwort wurde" +" an ihre EMail Addresse gesendet" + +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 +msgid "Changeset" +msgstr "" + +#: kallithea/controllers/pullrequests.py:157 +msgid "Special" +msgstr "" + +#: kallithea/controllers/pullrequests.py:158 +msgid "Peer branches" +msgstr "" + +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 +msgid "Bookmarks" +msgstr "Lesezeichen" + +#: kallithea/controllers/pullrequests.py:330 +msgid "Pull request requires a title with min. 3 chars" +msgstr "" + +#: kallithea/controllers/pullrequests.py:332 +#, python-format +msgid "Error creating pull request: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:354 +msgid "Successfully opened new pull request" +msgstr "Es wurde erfolgreich ein neuer Pullrequest eröffnet" + +#: kallithea/controllers/pullrequests.py:357 +msgid "Error occurred during sending pull request" +msgstr "Währen des abschicken des Pullrequests trat ein Fehler auf" + +#: kallithea/controllers/pullrequests.py:397 +msgid "Successfully deleted pull request" +msgstr "" + +#: kallithea/controllers/pullrequests.py:485 +msgid "Closing with" +msgstr "" + +#: kallithea/controllers/pullrequests.py:522 +msgid "Closing pull request on other statuses than rejected or approved forbidden" +msgstr "" + +#: kallithea/controllers/search.py:135 +msgid "Invalid search query. Try quoting it." +msgstr "Ungültige Suchanfrage. Versuchen sie es in Anführungzeichen zu setzen." + +#: kallithea/controllers/search.py:140 +msgid "There is no index to search in. Please run whoosh indexer" +msgstr "Es gibt keinen durchsuchbaren Index. Bitte den Whoosh Indizierer ausführen" + +#: kallithea/controllers/search.py:144 +msgid "An error occurred during this search operation" +msgstr "Während dieser Such Operation trat ein Fehler auf" + +#: kallithea/controllers/summary.py:203 +msgid "No data loaded yet" +msgstr "Es wurden bisher keine Daten geladen" + +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 +msgid "Statistics are disabled for this repository" +msgstr "Statistiken sind deaktiviert für dieses Repository" + +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:97 +msgid "Default settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:111 +msgid "Error occurred during update of defaults" +msgstr "" + +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 +msgid "forever" +msgstr "" + +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 +msgid "5 minutes" +msgstr "" + +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 +msgid "1 hour" +msgstr "" + +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 +msgid "1 day" +msgstr "" + +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 +msgid "1 month" +msgstr "" + +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 +msgid "Lifetime" +msgstr "" + +#: kallithea/controllers/admin/gists.py:147 +msgid "Error occurred during gist creation" +msgstr "" + +#: kallithea/controllers/admin/gists.py:185 +#, python-format +msgid "Deleted gist %s" +msgstr "" + +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "" +"Sie können diesen User nicht editieren da er für die ganze Applikation " +"von entscheidender bedeutung ist." + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "Ihr Account wurde erfolgreich aktualisiert" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "Die EMail Addresse %s wurde zum Benutzer hinzugefügt" + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "Währen der Speicherung der EMail Addresse trat ein Fehler auf" + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "Die EMail Addresse wurde vom Benutzer entfernt" + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 +msgid "None" +msgstr "Keine" + +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 +msgid "Read" +msgstr "Lesen" + +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 +msgid "Write" +msgstr "Schreiben" + +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 +msgid "Admin" +msgstr "Admin" + +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 +msgid "Disabled" +msgstr "Deaktiviert" + +#: kallithea/controllers/admin/permissions.py:78 +msgid "Allowed with manual account activation" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:80 +msgid "Allowed with automatic account activation" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 +msgid "Manual activation of external account" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 +msgid "Automatic activation of external account" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 +msgid "Enabled" +msgstr "Aktiviert" + +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:139 +msgid "Error occurred during update of permissions" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:186 +#, python-format +msgid "Created repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:198 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:256 +#, python-format +msgid "Updated repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:271 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:289 +#, python-format +msgid "This group contains %s repositores and cannot be deleted" +msgstr "Die Gruppe enthält %s Repositorys und kann nicht gelöscht werden" + +#: kallithea/controllers/admin/repo_groups.py:296 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:302 +#, python-format +msgid "Removed repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:237 +#, python-format +msgid "Created repository %s from %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:249 +#, python-format +msgid "Created repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:289 +#, python-format +msgid "Repository %s updated successfully" +msgstr "Repository %s wurde erfolgreich aktualisiert" + +#: kallithea/controllers/admin/repos.py:307 +#, python-format +msgid "Error occurred during update of repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:334 +#, python-format +msgid "Detached %s forks" +msgstr "" + +#: kallithea/controllers/admin/repos.py:337 +#, python-format +msgid "Deleted %s forks" +msgstr "" + +#: kallithea/controllers/admin/repos.py:342 +#, python-format +msgid "Deleted repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:345 +#, python-format +msgid "Cannot delete %s it still contains attached forks" +msgstr "%s konnte nicht gelöscht werden da es immernoch Forks enthält" + +#: kallithea/controllers/admin/repos.py:350 +#, python-format +msgid "An error occurred during deletion of %s" +msgstr "Beim Löschen von %s trat ein Fehler auf" + +#: kallithea/controllers/admin/repos.py:402 +msgid "Repository permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "" + +#: kallithea/controllers/admin/repos.py:522 +msgid "Updated repository visibility in public journal" +msgstr "Sichtbarkeit des Repositorys im Öffentlichen Logbuch aktualisiert" + +#: kallithea/controllers/admin/repos.py:526 +msgid "An error occurred during setting this repository in public journal" +msgstr "" +"Es trat ein Fehler während der Aktualisierung der Sicherbarkeit dieses " +"Repositorys im Öffentlichen Logbuch auf" + +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 +msgid "Token mismatch" +msgstr "Schlüssel stimmt nicht überein" + +#: kallithea/controllers/admin/repos.py:546 +msgid "Nothing" +msgstr "Nichts" + +#: kallithea/controllers/admin/repos.py:548 +#, python-format +msgid "Marked repo %s as fork of %s" +msgstr "Markiere Repository %s als Abzweig von Repository %s" + +#: kallithea/controllers/admin/repos.py:555 +msgid "An error occurred during this operation" +msgstr "Während dieser operation trat ein Fehler auf" + +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 +msgid "An error occurred during unlocking" +msgstr "" + +#: kallithea/controllers/admin/repos.py:595 +msgid "Unlocked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:598 +msgid "Locked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:600 +#, python-format +msgid "Repository has been %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "Währen der Cache Invalidierung trat ein Fehler auf" + +#: kallithea/controllers/admin/repos.py:637 +msgid "Pulled from remote location" +msgstr "Von entferntem Ort übertragen" + +#: kallithea/controllers/admin/repos.py:640 +msgid "An error occurred during pull from remote location" +msgstr "" +"Es trat ein Fehler auf während das Repository von einem Entfernten " +"Speicherort übertragen wurde" + +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "Während des löschens der Repository Statistiken trat ein Fehler auf" + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:176 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:215 +#, python-format +msgid "Repositories successfully rescanned added: %s ; removed: %s" +msgstr "" + +#: kallithea/controllers/admin/settings.py:270 +msgid "Updated application settings" +msgstr "Aktualisiere Applikations Einstellungen" + +#: kallithea/controllers/admin/settings.py:327 +msgid "Updated visualisation settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:332 +msgid "Error occurred during updating visualisation settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "" + +#: kallithea/controllers/admin/settings.py:400 +msgid "Added new hook" +msgstr "Neuer Hook hinzugefügt" + +#: kallithea/controllers/admin/settings.py:414 +msgid "Updated hooks" +msgstr "Die Hooks wurden aktutalisiert" + +#: kallithea/controllers/admin/settings.py:418 +msgid "Error occurred during hook creation" +msgstr "" + +#: kallithea/controllers/admin/settings.py:444 +msgid "Whoosh reindex task scheduled" +msgstr "Whoosh Reindizierungs Aufgabe wurde zur Ausführung geplant" + +#: kallithea/controllers/admin/user_groups.py:150 +#, python-format +msgid "Created user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:161 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Updated user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:221 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:239 +msgid "Successfully deleted user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:244 +msgid "An error occurred during deletion of user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:311 +msgid "Target group cannot be the same" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:317 +msgid "User Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "" + +#: kallithea/controllers/admin/users.py:135 +#, python-format +msgid "Created user %s" +msgstr "" + +#: kallithea/controllers/admin/users.py:149 +#, python-format +msgid "Error occurred during creation of user %s" +msgstr "" + +#: kallithea/controllers/admin/users.py:188 +msgid "User updated successfully" +msgstr "Der Benutzer wurde erfolgreich aktualisiert" + +#: kallithea/controllers/admin/users.py:223 +msgid "Successfully deleted user" +msgstr "" + +#: kallithea/controllers/admin/users.py:228 +msgid "An error occurred during deletion of user" +msgstr "Während der Löschen des Benutzers trat ein Fehler auf" + +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 +msgid "You can't edit this user" +msgstr "Sie können diesen Benutzer nicht editieren" + +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "" + +#: kallithea/controllers/admin/users.py:489 +msgid "An error occurred during ip saving" +msgstr "" + +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "" + +#: kallithea/lib/auth.py:748 +#, python-format +msgid "IP %s not allowed" +msgstr "" + +#: kallithea/lib/auth.py:809 +msgid "You need to be a registered user to perform this action" +msgstr "Sie müssen ein Registrierter Nutzer sein um diese Aktion durchzuführen" + +#: kallithea/lib/auth.py:846 +msgid "You need to be a signed in to view this page" +msgstr "Sie müssen sich anmelden um diese Seite aufzurufen" + +#: kallithea/lib/diffs.py:66 +msgid "Binary file" +msgstr "" + +#: kallithea/lib/diffs.py:82 +msgid "Changeset was too big and was cut off, use diff menu to display this diff" +msgstr "" +"Der Änderungssatz war zu groß und wurde abgeschnitten, benutzen sie das " +"Diff Menü um die Unterschiede anzuzeigen" + +#: kallithea/lib/diffs.py:92 +msgid "No changes detected" +msgstr "Keine Änderungen erkannt" + +#: kallithea/lib/helpers.py:598 +#, python-format +msgid "Deleted branch: %s" +msgstr "" + +#: kallithea/lib/helpers.py:601 +#, python-format +msgid "Created tag: %s" +msgstr "" + +#: kallithea/lib/helpers.py:614 +msgid "Changeset not found" +msgstr "Änderungssatz nicht gefunden" + +#: kallithea/lib/helpers.py:664 +#, python-format +msgid "Show all combined changesets %s->%s" +msgstr "Zeige alle Kombinierten Änderungensätze %s->%s" + +#: kallithea/lib/helpers.py:670 +msgid "compare view" +msgstr "vergleichsansicht" + +#: kallithea/lib/helpers.py:690 +msgid "and" +msgstr "und" + +#: kallithea/lib/helpers.py:691 +#, python-format +msgid "%s more" +msgstr "%s mehr" + +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 +msgid "revisions" +msgstr "revisionen" + +#: kallithea/lib/helpers.py:716 +#, python-format +msgid "fork name %s" +msgstr "" + +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 +#, python-format +msgid "Pull request #%s" +msgstr "" + +#: kallithea/lib/helpers.py:743 +msgid "[deleted] repository" +msgstr "[gelöscht] Repository" + +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 +msgid "[created] repository" +msgstr "[erstellt] Repository" + +#: kallithea/lib/helpers.py:747 +msgid "[created] repository as fork" +msgstr "[erstellt] Repository als Fork" + +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 +msgid "[forked] repository" +msgstr "[forked] Repository" + +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 +msgid "[updated] repository" +msgstr "[aktualisiert] Repository" + +#: kallithea/lib/helpers.py:753 +msgid "[downloaded] archive from repository" +msgstr "" + +#: kallithea/lib/helpers.py:755 +msgid "[delete] repository" +msgstr "[gelöscht] Repository" + +#: kallithea/lib/helpers.py:763 +msgid "[created] user" +msgstr "[erstellt] Benutzer" + +#: kallithea/lib/helpers.py:765 +msgid "[updated] user" +msgstr "[akutalisiert] Benutzer" + +#: kallithea/lib/helpers.py:767 +msgid "[created] user group" +msgstr "" + +#: kallithea/lib/helpers.py:769 +msgid "[updated] user group" +msgstr "" + +#: kallithea/lib/helpers.py:771 +msgid "[commented] on revision in repository" +msgstr "[kommentiert] revision in Repository" + +#: kallithea/lib/helpers.py:773 +msgid "[commented] on pull request for" +msgstr "" + +#: kallithea/lib/helpers.py:775 +msgid "[closed] pull request for" +msgstr "" + +#: kallithea/lib/helpers.py:777 +msgid "[pushed] into" +msgstr "[übermittelt] in" + +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "" + +#: kallithea/lib/helpers.py:781 +msgid "[pulled from remote] into repository" +msgstr "" + +#: kallithea/lib/helpers.py:783 +msgid "[pulled] from" +msgstr "" + +#: kallithea/lib/helpers.py:785 +msgid "[started following] repository" +msgstr "" + +#: kallithea/lib/helpers.py:787 +msgid "[stopped following] repository" +msgstr "" + +#: kallithea/lib/helpers.py:1101 +#, python-format +msgid " and %s more" +msgstr "und %s weitere" + +#: kallithea/lib/helpers.py:1105 +msgid "No Files" +msgstr "Keine Dateien" + +#: kallithea/lib/helpers.py:1171 +msgid "new file" +msgstr "" + +#: kallithea/lib/helpers.py:1174 +msgid "mod" +msgstr "" + +#: kallithea/lib/helpers.py:1177 +msgid "del" +msgstr "" + +#: kallithea/lib/helpers.py:1180 +msgid "rename" +msgstr "" + +#: kallithea/lib/helpers.py:1185 +msgid "chmod" +msgstr "" + +#: kallithea/lib/helpers.py:1417 +#, python-format +msgid "" +"%s repository is not mapped to db perhaps it was created or renamed from " +"the filesystem please run the application again in order to rescan " +"repositories" +msgstr "" +"Das %s Repository ist nicht in der Datenbank vorhanden, eventuell wurde " +"es im Dateisystem erstellt oder umbenannt. Bitte starten sie die " +"Applikation erneut um die Repositories neu zu Indizieren" + +#: kallithea/lib/utils2.py:415 +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d Jahr" +msgstr[1] "%d Jahre" + +#: kallithea/lib/utils2.py:416 +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d Monat" +msgstr[1] "%d Monate" + +#: kallithea/lib/utils2.py:417 +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d Tag" +msgstr[1] "%d Tage" + +#: kallithea/lib/utils2.py:418 +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d Stunde" +msgstr[1] "%d Stunden" + +#: kallithea/lib/utils2.py:419 +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d Minute" +msgstr[1] "%d Minuten" + +#: kallithea/lib/utils2.py:420 +#, python-format +msgid "%d second" +msgid_plural "%d seconds" +msgstr[0] "%d Sekunde" +msgstr[1] "%d Sekunden" + +#: kallithea/lib/utils2.py:436 +#, python-format +msgid "in %s" +msgstr "" + +#: kallithea/lib/utils2.py:438 +#, python-format +msgid "%s ago" +msgstr "vor %s" + +#: kallithea/lib/utils2.py:440 +#, python-format +msgid "in %s and %s" +msgstr "" + +#: kallithea/lib/utils2.py:443 +#, python-format +msgid "%s and %s ago" +msgstr "%s und %s her" + +#: kallithea/lib/utils2.py:446 +msgid "just now" +msgstr "jetzt gerade" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 +msgid "Repository no access" +msgstr "Kein Zugriff auf Repository" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 +msgid "Repository read access" +msgstr "Lesender Zugriff auf Repository" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 +msgid "Repository write access" +msgstr "Schreibdender Zugriff auf Repository" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 +msgid "Repository admin access" +msgstr "Administrativer Zugang zum Repository" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 +msgid "Repositories Group no access" +msgstr "Repository Gruppe hat Keinen Zugriff" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 +msgid "Repositories Group read access" +msgstr "Repository Gruppe hat lesenden Zugriff" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 +msgid "Repositories Group write access" +msgstr "Repository Gruppe hat schreibenden Zugriff" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 +msgid "Repositories Group admin access" +msgstr "Repository Gruppe hat Administrativen Zugriff" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" +msgstr "Kallithea Administrator" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 +msgid "Repository creation disabled" +msgstr "Repository erstelllung deaktiviert" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 +msgid "Repository creation enabled" +msgstr "Repository erstellung aktiviert" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 +msgid "Repository forking disabled" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 +msgid "Repository forking enabled" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 +msgid "Register disabled" +msgstr "Registrierung deaktiviert" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" +msgstr "Registrierung neuer Benutzer in Kallithea mit manueller Aktivierung" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" +msgstr "Registrierung neuer Benutzer in Kallithea mit Automatischer Aktivierung" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 +msgid "Not Reviewed" +msgstr "Nicht Begutachtet" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 +msgid "Approved" +msgstr "Akzeptiert" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 +msgid "Rejected" +msgstr "Abgelehnt" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 +msgid "Under Review" +msgstr "In Begutachtung" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 +msgid "top level" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 +msgid "Repository group no access" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 +msgid "Repository group read access" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 +msgid "Repository group write access" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 +msgid "Repository group admin access" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 +msgid "User group no access" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 +msgid "User group read access" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 +msgid "User group write access" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 +msgid "User group admin access" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 +msgid "Repository Group creation disabled" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 +msgid "Repository Group creation enabled" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 +msgid "User Group creation disabled" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 +msgid "User Group creation enabled" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 +msgid "Registration disabled" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 +msgid "User Registration with manual account activation" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 +msgid "User Registration with automatic account activation" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:77 +#, python-format +msgid "on line %s" +msgstr "in Zeile %s" + +#: kallithea/model/comment.py:222 +msgid "[Mention]" +msgstr "[Mention]" + +#: kallithea/model/forms.py:57 +msgid "Please enter a login" +msgstr "Bitte einen Benutzernamen eingeben" + +#: kallithea/model/forms.py:58 +#, python-format +msgid "Enter a value %(min)i characters long or more" +msgstr "Bitte einen Wert mit mindestens %(min)i Zeichen eingeben" + +#: kallithea/model/forms.py:66 +msgid "Please enter a password" +msgstr "Bitte ein Passwort eingeben" + +#: kallithea/model/forms.py:67 +#, python-format +msgid "Enter %(min)i characters or more" +msgstr "Bitte mindestens %(min)i Zeichen eingeben" + +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:231 +#, python-format +msgid "%(user)s commented on changeset at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:232 +#, python-format +msgid "%(user)s sent message at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:233 +#, python-format +msgid "%(user)s mentioned you at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:234 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:235 +#, python-format +msgid "%(user)s opened new pull request at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:236 +#, python-format +msgid "%(user)s commented on pull request at %(when)s" +msgstr "" + +#: kallithea/model/pull_request.py:107 +#, python-format +msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" +msgstr "" + +#: kallithea/model/scm.py:810 +msgid "latest tip" +msgstr "" + +#: kallithea/model/user.py:198 +msgid "New user registration" +msgstr "" + +#: kallithea/model/user.py:222 kallithea/model/user.py:247 +msgid "You can't Edit this user since it's crucial for entire application" +msgstr "" +"Sie können diesen User nicht editieren da er für die ganze Applikation " +"von entscheidender bedeutung ist." + +#: kallithea/model/user.py:270 +msgid "You can't remove this user since it's crucial for entire application" +msgstr "" +"Sie können diesen User nicht löschen da er für die ganze Applikation von " +"entscheidender bedeutung ist." + +#: kallithea/model/user.py:276 +#, python-format +msgid "" +"user \"%s\" still owns %s repositories and cannot be removed. Switch " +"owners or remove those repositories. %s" +msgstr "" + +#: kallithea/model/user.py:304 +msgid "Password reset link" +msgstr "" + +#: kallithea/model/user.py:333 +msgid "Your new password" +msgstr "" + +#: kallithea/model/user.py:334 +#, python-format +msgid "Your new Kallithea password:%s" +msgstr "" + +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 +msgid "Value cannot be an empty list" +msgstr "" + +#: kallithea/model/validators.py:120 +#, python-format +msgid "Username \"%(username)s\" already exists" +msgstr "Benutezrname \"%(username)s\" existiert bereits" + +#: kallithea/model/validators.py:122 +#, python-format +msgid "Username \"%(username)s\" is forbidden" +msgstr "Benutzername \"%(username)s\" ist verboten" + +#: kallithea/model/validators.py:124 +msgid "" +"Username may only contain alphanumeric characters underscores, periods or" +" dashes and must begin with alphanumeric character or underscore" +msgstr "" + +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:158 +#, python-format +msgid "Username %(username)s is not valid" +msgstr "Benutzername \"%(username)s\" ist ungültig" + +#: kallithea/model/validators.py:177 +msgid "Invalid user group name" +msgstr "" + +#: kallithea/model/validators.py:178 +#, python-format +msgid "User group \"%(usergroup)s\" already exists" +msgstr "" + +#: kallithea/model/validators.py:180 +msgid "" +"user group name may only contain alphanumeric characters underscores, " +"periods or dashes and must begin with alphanumeric character" +msgstr "" + +#: kallithea/model/validators.py:218 +msgid "Cannot assign this group as parent" +msgstr "Kann diese Gruppe nicht als vorgesetzt setzen" + +#: kallithea/model/validators.py:219 +#, python-format +msgid "Group \"%(group_name)s\" already exists" +msgstr "Gruppe \"%(group_name)s\" existiert bereits" + +#: kallithea/model/validators.py:221 +#, python-format +msgid "Repository with name \"%(group_name)s\" already exists" +msgstr "Es gibt bereits ein Repository mit \"%(group_name)s\"" + +#: kallithea/model/validators.py:279 +msgid "Invalid characters (non-ascii) in password" +msgstr "Üngültige(nicht ASCII) Zeichen im Passwort" + +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 +msgid "Passwords do not match" +msgstr "Die Passwörter stimmen nicht überein" + +#: kallithea/model/validators.py:327 +msgid "invalid password" +msgstr "Ungültiges Passwort" + +#: kallithea/model/validators.py:328 +msgid "invalid user name" +msgstr "Ungültiger Benutzername" + +#: kallithea/model/validators.py:329 +msgid "Your account is disabled" +msgstr "Ihr Account wurde Deaktiviert" + +#: kallithea/model/validators.py:373 +#, python-format +msgid "Repository name %(repo)s is disallowed" +msgstr "Repository Name \"%(repo)s\" ist verboten" + +#: kallithea/model/validators.py:375 +#, python-format +msgid "Repository named %(repo)s already exists" +msgstr "Es gibt bereits ein Repository mit \"%(repo)s\"" + +#: kallithea/model/validators.py:376 +#, python-format +msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" +msgstr "" +"Es gibt bereits ein Repository mit \"%(repo)s\" in der Gruppe " +"\"%(group)s\"" + +#: kallithea/model/validators.py:378 +#, python-format +msgid "Repository group with name \"%(repo)s\" already exists" +msgstr "" + +#: kallithea/model/validators.py:493 +msgid "invalid clone url" +msgstr "ungültige Clone Adresse" + +#: kallithea/model/validators.py:494 +msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" +msgstr "" + +#: kallithea/model/validators.py:519 +msgid "Fork have to be the same type as parent" +msgstr "Forke um den selben typ wie der Vorgesetze zu haben" + +#: kallithea/model/validators.py:534 +msgid "You don't have permissions to create repository in this group" +msgstr "" + +#: kallithea/model/validators.py:536 +msgid "no permission to create repository in root location" +msgstr "" + +#: kallithea/model/validators.py:585 +msgid "You don't have permissions to create a group in this location" +msgstr "" + +#: kallithea/model/validators.py:626 +msgid "This username or user group name is not valid" +msgstr "" + +#: kallithea/model/validators.py:719 +msgid "This is not a valid path" +msgstr "Dies ist ein Ungültiger Pfad" + +#: kallithea/model/validators.py:734 +msgid "This e-mail address is already taken" +msgstr "Diese EMail Addresse ist schon in Benutzung" + +#: kallithea/model/validators.py:754 +#, python-format +msgid "e-mail \"%(email)s\" does not exist." +msgstr "EMail Addresse \"%(email)s\" existiert nicht." + +#: kallithea/model/validators.py:791 +msgid "" +"The LDAP Login attribute of the CN must be specified - this is the name " +"of the attribute that is equivalent to \"username\"" +msgstr "" +"Das LDAP Login Attribut des CN muss angeben werden - Es ist der Name des " +"Attributes welches das Equivalent zum \"Benutzername\" ist" + +#: kallithea/model/validators.py:804 +#, python-format +msgid "Revisions %(revs)s are already part of pull request or have set status" +msgstr "" + +#: kallithea/model/validators.py:836 +msgid "Please enter a valid IPv4 or IpV6 address" +msgstr "" + +#: kallithea/model/validators.py:837 +#, python-format +msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" +msgstr "" + +#: kallithea/model/validators.py:870 +msgid "Key name can only consist of letters, underscore, dash or numbers" +msgstr "" + +#: kallithea/model/validators.py:884 +msgid "Filename cannot be inside a directory" +msgstr "" + +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" +msgstr "" + +#: kallithea/templates/index.html:5 +msgid "Dashboard" +msgstr "Übersichtsseite" + +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 +msgid "quick filter..." +msgstr "Schnellfilter..." + +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 +msgid "repositories" +msgstr "Repositories" + +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" +msgstr "" + +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:32 +msgid "You have admin right to this group, and can edit it" +msgstr "" + +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" +msgstr "" + +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 +msgid "Description" +msgstr "Beschreibung" + +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 +msgid "Name" +msgstr "Name" + +#: kallithea/templates/index_base.html:129 +msgid "Last Change" +msgstr "Letzte Änderung" + +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 +msgid "Tip" +msgstr "" + +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 +msgid "Owner" +msgstr "Besitzer" + +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 +msgid "Click to sort ascending" +msgstr "Klicken um Aufsteigend zu Sortieren" + +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 +msgid "Click to sort descending" +msgstr "Klicken um Absteigend zu Sortieren" + +#: kallithea/templates/index_base.html:143 +msgid "No repositories found." +msgstr "" + +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 +msgid "Data error." +msgstr "Datenfehler." + +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 +msgid "Loading..." +msgstr "Lade..." + +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 +msgid "Log In" +msgstr "" + +#: kallithea/templates/login.html:30 +#, python-format +msgid "Log In to %s" +msgstr "" + +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 +msgid "Username" +msgstr "Benutzername" + +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 +msgid "Password" +msgstr "Passwort" + +#: kallithea/templates/login.html:62 +msgid "Remember me" +msgstr "Login Speichern" + +#: kallithea/templates/login.html:66 +msgid "Sign In" +msgstr "Einloggen" + +#: kallithea/templates/login.html:72 +msgid "Forgot your password ?" +msgstr "Passowrt Vergessen?" + +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 +msgid "Don't have an account ?" +msgstr "Kein Account?" + +#: kallithea/templates/password_reset.html:5 +msgid "Password Reset" +msgstr "" + +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" +msgstr "" + +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "" + +#: kallithea/templates/password_reset.html:64 +msgid "Password reset link will be send to matching email address" +msgstr "Der Passwort Reset LInk wird an die passende EMail Addresse gesendet" + +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 +msgid "Sign Up" +msgstr "Registrieren" + +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:58 +msgid "Re-enter password" +msgstr "Passwort erneut eingeben" + +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 +msgid "First Name" +msgstr "Vorname" + +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 +msgid "Last Name" +msgstr "Nachname" + +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 +msgid "Email" +msgstr "EMail" + +#: kallithea/templates/register.html:108 +msgid "Your account will be activated right after registration" +msgstr "Ihr Account muss direkt nach der Registrierung aktiviert werden" + +#: kallithea/templates/register.html:110 +msgid "Your account must wait for activation by administrator" +msgstr "Ihr Account muss durch einen Administrator aktiviert werden" + +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 +msgid "There are no branches yet" +msgstr "Es gibt bisher keine Branches" + +#: kallithea/templates/switch_to_list.html:16 +msgid "Closed Branches" +msgstr "" + +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 +msgid "There are no tags yet" +msgstr "Es gibt bisher keine Tags" + +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 +msgid "There are no bookmarks yet" +msgstr "Es gibt bisher keine Lesezeichen" + +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 +msgid "Admin journal" +msgstr "Admin Logbuch" + +#: kallithea/templates/admin/admin.html:13 +msgid "journal filter..." +msgstr "Logbuch filter..." + +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 +msgid "filter" +msgstr "" + +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 +#, python-format +msgid "%s entry" +msgid_plural "%s entries" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 +msgid "Action" +msgstr "Aktion" + +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 +msgid "Repository" +msgstr "Repository" + +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 +msgid "Date" +msgstr "Datum" + +#: kallithea/templates/admin/admin_log.html:9 +msgid "From IP" +msgstr "Von IP" + +#: kallithea/templates/admin/admin_log.html:63 +msgid "No actions yet" +msgstr "Es sind bisher keine Aktionen passiert" + +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "" +"Comma separated list of plugins. Order of plugins is also order in which " +"Kallithea will try to authenticate user" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "Speichern" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 +msgid "Repositories defaults" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 +msgid "Defaults" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 +msgid "Type" +msgstr "Typ" + +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "Privates Repository" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 +msgid "" +"Private repositories are only visible to people explicitly added as " +"collaborators." +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 +msgid "Enable statistics" +msgstr "Aktiviere Statistiken" + +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 +msgid "Enable statistics window on summary page." +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 +msgid "Enable downloads" +msgstr "Aktiviere Downloads" + +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 +msgid "Enable download menu on summary page." +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 +msgid "Enable locking" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 +msgid "Enable lock-by-pulling on repository." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "" +"Gist was update since you started editing. Copy your changes and click " +"%(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 +#, python-format +msgid "Private Gists for user %s" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 +#, python-format +msgid "Public Gists for user %s" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 +msgid "Public Gists" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 +msgid "Created" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:77 +msgid "There are no gists yet" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 +msgid "Reset" +msgstr "Zurücksetzen" + +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 +msgid "Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 +msgid "Delete" +msgstr "Löschen" + +#: kallithea/templates/admin/gists/show.html:59 +msgid "Confirm to delete this Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:76 +msgid "created" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "Mein Account" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" +msgstr "Mein Account" + +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "Pull Request" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "Meine Rechte" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "Hinzufügen" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "löschen" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "" +"Your user is in an external Source of Record; some details cannot be " +"managed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "Keine Datensätze gefunden." + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 +msgid "My Notifications" +msgstr "Meine Benachrichtigungen" + +#: kallithea/templates/admin/notifications/notifications.html:32 +msgid "All" +msgstr "Alle" + +#: kallithea/templates/admin/notifications/notifications.html:33 +msgid "Comments" +msgstr "Kommentare" + +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:38 +msgid "Mark all read" +msgstr "Markiere alle als gelesen" + +#: kallithea/templates/admin/notifications/notifications_data.html:40 +msgid "No notifications here yet" +msgstr "Bisher gibt es keine Benachrichtigungen" + +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 +msgid "Show notification" +msgstr "Zeige Benachrichtigung" + +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 +msgid "Notifications" +msgstr "Benachrichtigungen" + +#: kallithea/templates/admin/permissions/permissions.html:5 +msgid "Permissions administration" +msgstr "Rechte Administration" + +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 +msgid "Permissions" +msgstr "Rechte" + +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 +msgid "Anonymous access" +msgstr "Anonymer Zugang" + +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without need to log in. Anonymous users use %s " +"user permissions" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 +msgid "" +"All default permissions on each repository will be reset to chosen " +"permission, note that all custom default permission on repositories will " +"be lost" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 +msgid "Overwrite existing settings" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "Repository Gruppe" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 +msgid "" +"All default permissions on each repository group will be reset to chosen " +"permission, note that all custom default permission on repository groups " +"will be lost" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 +msgid "User group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:53 +msgid "" +"All default permissions on each user group will be reset to chosen " +"permission, note that all custom default permission on repository groups " +"will be lost" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:60 +msgid "Repository creation" +msgstr "Repository erstellung" + +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "" +"Write permission to repository groups allows creating repositories inside" +" that group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 +msgid "User group creation" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:85 +msgid "Repository forking" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:93 +msgid "Registration" +msgstr "Registrierung" + +#: kallithea/templates/admin/permissions/permissions_globals.html:101 +msgid "External auth account activation" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 +#, python-format +msgid "Confirm to delete this ip: %s" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 +msgid "All IP addresses are allowed" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 +msgid "New ip address" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "Gruppen name" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 +msgid "Settings" +msgstr "Einstellungen" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 +#, python-format +msgid "Confirm to delete this group: %s with %s repository" +msgid_plural "Confirm to delete this group: %s with %s repositories" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "keine" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "lesen" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "schreiben" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "admin" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "standart" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "entziehen" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "" +"Set or revoke permission to all children of that group, including non-" +"private repositories and other groups if selected." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "" +"Enable lock-by-pulling on group. This option will be applied to all other" +" groups and repositories inside" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "%s Repository group dashboard" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "mit" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "Neues Repository" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "Clone von" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "Optionale http[s] URL von diesem das Repository geclont werden soll." + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "" +"Wähle optional eine Gruppe in welcher das Repository platziert werden " +"soll." + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "Repository Typ der erstellt werden soll." + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "Start Revision" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is beeing created, you will be redirected " +"when this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:42 +msgid "" +"We're sorry but error occured during this operation. Please check your " +"Kallithea server logs, or contact administrator." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, python-format +msgid "%s repository settings" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +msgid "Remote" +msgstr "Entfernt" + +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "Statistiken" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "Sichtbarkeit des Öffentlichen Logbuches" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Remove from public journal" +msgstr "Entferne aus dem Öffentlichen Logbuch" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +msgid "Add to public journal" +msgstr "Zum Öffentlichen Logbuch hinzufügen" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 +msgid "" +"All actions made on this repository will be accessible to everyone in " +"public journal" +msgstr "" +"Alle Aktionen die in diesem Repository durchgeführt wurden sind für jeden" +" Zugänglich im Öffentlichen Logbuch" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 +msgid "Confirm to unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 +msgid "Confirm to lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 +msgid "Repository is not locked" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 +msgid "" +"Force locking on repository. Works only when anonymous access is " +"disabled. Trigering a pull locks repository by user who pulled, only the " +"same user can unlock by doing a push" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +msgid "Delete this repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 +#, python-format +msgid "this repository has %s fork" +msgid_plural "this repository has %s forks" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 +msgid "Detach forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 +msgid "Delete forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "" +"This repository will be renamed in a special way in order to be " +"unaccesible for Kallithea and VCS systems. If you need to fully delete it" +" from file system please do it manually" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 +msgid "" +"Manually invalidate cache for this repository. On first access repository" +" will be cached again" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "Aktiv" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#, python-format +msgid "Confirm to delete this field: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 +msgid "New field key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 +msgid "New field label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 +msgid "Enter short label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 +msgid "New field description" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +msgid "Enter description of a field" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 +msgid "private repository" +msgstr "privates Repository" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 +msgid "" +"In case this repository is renamed or moved into another group the " +"repository url changes.\n" +" Using above url guarantees that this " +"repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases" +" that you need to hardcode the url into 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "bearbeiten" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "" + +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 +msgid "Settings administration" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:16 +msgid "SMTP auth" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:39 +msgid "Send" +msgstr "Senden" + +#: kallithea/templates/admin/settings/settings_global.html:8 +msgid "Site branding" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:18 +msgid "HTTP authentication realm" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:27 +msgid "Google Analytics code" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:50 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 +msgid "Save settings" +msgstr "Einstellungen speichern" + +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "" +"Hooks can be used to trigger actions on certain events such as push / " +"pull. They can trigger Python functions or external applications." +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 +msgid "Custom hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:69 +msgid "Failed to remove hook" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:6 +msgid "Rescan option" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:11 +msgid "Destroy old data" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:13 +msgid "" +"In case a repository was deleted from filesystem and it still exists in " +"the database check this option to scan obsolete data in database and " +"remove it." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 +msgid "" +"Each cache data for repositories will be cleaned with this option " +"selected. Use this to reload data and clear cache keys." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 +msgid "" +"Verify if Kallitheas GIT hooks are installed for each repository. Current" +" hooks will be updated to latest version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:7 +msgid "Index build option" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:12 +msgid "Build from scratch" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:15 +msgid "" +"This option completely reindex all the files within Kallithea for proper " +"fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:21 +msgid "Reindex" +msgstr "Erneut Indizieren" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 +msgid "Web" +msgstr "Web" + +#: kallithea/templates/admin/settings/settings_vcs.html:11 +msgid "Require SSL for vcs operations" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:13 +msgid "" +"Activate to set Kallithea to require SSL for pushing or pulling. If SSL " +"certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 +msgid "Show repository size after push" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:28 +msgid "Log user push commands" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:32 +msgid "Log user pull commands" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:36 +msgid "Update repository after push (hg update)" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:42 +msgid "Mercurial Extensions" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:47 +msgid "Enable largefiles extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:51 +msgid "Enable hgsubversion extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:53 +msgid "" +"Requires hgsubversion library to be installed. Allows cloning remote SVN " +"repositories and migrates them to Mercurial type." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 +msgid "Repositories location" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting" +" take effect." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:72 +msgid "" +"Filesystem location where repositories should be stored. After changing " +"this value a restart and rescan of the repository folder are required." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:8 +msgid "General" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:13 +msgid "Use repository extra fields" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:15 +msgid "Allows storing additional customized fields per repository." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:30 +msgid "" +"Gravatar url allows you to use other avatar server application.\n" +" Following " +"variables of the URL will be replaced accordingly.\n" +" {scheme} " +"'http' or 'https' sent from running Kallithea server,\n" +" {email} user " +"email,\n" +" {md5email} md5 " +"hash of the user email (like at gravatar.com),\n" +" {size} size " +"of the image that is expected from the server application,\n" +" {netloc} " +"network location/server host of running Kallithea server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:42 +msgid "" +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}'," +" available vars:\n" +" {scheme} 'http' " +"or 'https' sent from running Kallithea server,\n" +" {user} current " +"user username,\n" +" {netloc} network " +"location/server host of running Kallithea server,\n" +" {repo} full " +"repository name,\n" +" {repoid} ID of " +"repository, can be used to contruct clone-by-id" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:54 +msgid "Dashboard items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:58 +msgid "" +"Number of items displayed in the main page dashboard before pagination is" +" shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:68 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:74 +msgid "Icons" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:79 +msgid "Show public repo icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:83 +msgid "Show private repo icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:91 +msgid "Meta-Tagging" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:110 +msgid "" +"Parses meta tags from repository description field and turns them into " +"colored tags." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 +msgid "Add user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 +msgid "User groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 +#, python-format +msgid "%s user group settings" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "Standart Rechte" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 +msgid "Members" +msgstr "Mitglieder" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 +#, python-format +msgid "User Group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 +#, python-format +msgid "Confirm to delete this user group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 +msgid "Add user" +msgstr "Benutzer hinzufügen" + +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 +msgid "Users" +msgstr "Benutzer" + +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:53 +msgid "Password confirmation" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:5 +#, python-format +msgid "%s user settings" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 +#, python-format +msgid "" +"This user is in an external Source of Record (%s); some details cannot be" +" managed here." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 +msgid "New password confirmation" +msgstr "" + +#: kallithea/templates/admin/users/users.html:5 +msgid "Users administration" +msgstr "" + +#: kallithea/templates/admin/users/users.html:13 +msgid "users" +msgstr "" + +#: kallithea/templates/admin/users/users.html:54 +msgid "Firstname" +msgstr "" + +#: kallithea/templates/admin/users/users.html:55 +msgid "Lastname" +msgstr "" + +#: kallithea/templates/admin/users/users.html:56 +msgid "Last login" +msgstr "" + +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "" + +#: kallithea/templates/base/base.html:37 +#, python-format +msgid "Server instance: %s" +msgstr "" + +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 +msgid "Summary" +msgstr "" + +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 +msgid "Changelog" +msgstr "" + +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 +msgid "Files" +msgstr "" + +#: kallithea/templates/base/base.html:149 +msgid "Switch To" +msgstr "" + +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 +msgid "Options" +msgstr "" + +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 +msgid "Compare fork" +msgstr "" + +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 +msgid "Search" +msgstr "" + +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "" + +#: kallithea/templates/base/base.html:176 +msgid "Lock" +msgstr "" + +#: kallithea/templates/base/base.html:184 +msgid "Follow" +msgstr "" + +#: kallithea/templates/base/base.html:185 +msgid "Unfollow" +msgstr "" + +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 +msgid "Fork" +msgstr "" + +#: kallithea/templates/base/base.html:190 +msgid "Create Pull Request" +msgstr "" + +#: kallithea/templates/base/base.html:196 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "" + +#: kallithea/templates/base/base.html:233 +msgid "Not logged in" +msgstr "" + +#: kallithea/templates/base/base.html:240 +msgid "Login to your account" +msgstr "" + +#: kallithea/templates/base/base.html:263 +msgid "Forgot password ?" +msgstr "" + +#: kallithea/templates/base/base.html:286 +msgid "Log Out" +msgstr "" + +#: kallithea/templates/base/base.html:311 +msgid "Show recent activity" +msgstr "" + +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 +msgid "Journal" +msgstr "Logbuch" + +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "Öffentliches Logbuch" + +#: kallithea/templates/base/base.html:323 +msgid "Show public gists" +msgstr "" + +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "" + +#: kallithea/templates/base/base.html:328 +msgid "All public gists" +msgstr "" + +#: kallithea/templates/base/base.html:330 +msgid "My public gists" +msgstr "" + +#: kallithea/templates/base/base.html:331 +msgid "My private gists" +msgstr "" + +#: kallithea/templates/base/base.html:336 +msgid "Search in repositories" +msgstr "" + +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:19 +#, python-format +msgid "" +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:28 +msgid "Create repositories" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:33 +msgid "Select this option to allow repository creation for this user" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:40 +msgid "Create user groups" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:45 +msgid "Select this option to allow user group creation for this user" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:52 +msgid "Fork repositories" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:57 +msgid "Select this option to allow repository forking for this user" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:22 +msgid "No permissions defined yet" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 +msgid "Permission" +msgstr "Rechte" + +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 +msgid "Edit Permission" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 +msgid "Add another comment" +msgstr "" + +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 +msgid "Stop following this repository" +msgstr "" + +#: kallithea/templates/base/root.html:47 +msgid "Start following this repository" +msgstr "" + +#: kallithea/templates/base/root.html:48 +msgid "Group" +msgstr "" + +#: kallithea/templates/base/root.html:49 +msgid "members" +msgstr "mitglieder" + +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 +msgid "Loading ..." +msgstr "" + +#: kallithea/templates/base/root.html:51 +msgid "loading ..." +msgstr "" + +#: kallithea/templates/base/root.html:52 +msgid "Search truncated" +msgstr "" + +#: kallithea/templates/base/root.html:53 +msgid "No matching files" +msgstr "" + +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 +msgid "Open new pull request" +msgstr "" + +#: kallithea/templates/base/root.html:55 +msgid "Open new pull request for selected changesets" +msgstr "" + +#: kallithea/templates/base/root.html:56 +msgid "Show selected changesets __S -> __E" +msgstr "" + +#: kallithea/templates/base/root.html:57 +msgid "Show selected changeset __S" +msgstr "" + +#: kallithea/templates/base/root.html:58 +msgid "Selection link" +msgstr "" + +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 +msgid "Collapse diff" +msgstr "" + +#: kallithea/templates/base/root.html:60 +msgid "Expand diff" +msgstr "" + +#: kallithea/templates/base/root.html:61 +msgid "Failed to revoke permission" +msgstr "" + +#: kallithea/templates/base/root.html:62 +msgid "confirm to revoke permission for {0}: {1} ?" +msgstr "" + +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:5 +#, python-format +msgid "%s Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 +msgid "Author" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 +msgid "Revision" +msgstr "" + +#: kallithea/templates/branches/branches.html:5 +#, python-format +msgid "%s Branches" +msgstr "" + +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 +#, python-format +msgid "%s Changelog" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:21 +#, python-format +msgid "showing %d out of %d revision" +msgid_plural "showing %d out of %d revisions" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changelog/changelog.html:43 +msgid "Clear selection" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 +#, python-format +msgid "Compare fork with %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 +#, python-format +msgid "" +"Changeset status: %s\n" +"Click to open associated pull request #%s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 +#, python-format +msgid "Changeset status: %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:114 +msgid "Changeset has comments" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 +#, python-format +msgid "Bookmark %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 +#, python-format +msgid "Tag %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 +#, python-format +msgid "Branch %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:299 +msgid "There are no changes yet" +msgstr "" + +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 +msgid "Removed" +msgstr "" + +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 +msgid "Changed" +msgstr "" + +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 +msgid "Added" +msgstr "" + +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 +#, python-format +msgid "Affected %s files" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 +msgid "Commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:7 +msgid "Age" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:9 +msgid "Refs" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:95 +msgid "Push new repo" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:103 +msgid "Existing repository?" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:6 +#, python-format +msgid "%s Changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 +msgid "Changeset status" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 +msgid "Raw diff" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:58 +msgid "Patch diff" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 +msgid "Download diff" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 +#, python-format +msgid "%d comment" +msgid_plural "%d comments" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 +#, python-format +msgid "(%d inline)" +msgid_plural "(%d inline)" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 +msgid "merge" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 +#, python-format +msgid "%s file changed" +msgid_plural "%s files changed" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 +#, python-format +msgid "%s file changed with %s insertions and %s deletions" +msgid_plural "%s files changed with %s insertions and %s deletions" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 +msgid "Showing a huge diff might take some time and resources" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 +msgid "Show full diff" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 +#, python-format +msgid "Vote on pull request #%s" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 +#, python-format +msgid "Comment on pull request #%s" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Status change on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Comment on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:63 +msgid "Submitting..." +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:66 +msgid "Commenting on line {1}." +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 +#, python-format +msgid "Comments parsed using %s syntax with %s support." +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 +msgid "Preview" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 +msgid "Comment preview" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 +msgid "Comment" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:96 +msgid "You need to be logged in to comment." +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:96 +msgid "Login now" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:100 +msgid "Hide" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:159 +msgid "Vote for pull request status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:161 +msgid "Change changeset status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:179 +msgid "Close (when approved or rejected)" +msgstr "" + +#: kallithea/templates/changeset/changeset_range.html:5 +#, python-format +msgid "%s Changesets" +msgstr "" + +#: kallithea/templates/changeset/changeset_range.html:59 +msgid "Files affected" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 +msgid "Show full diff for this file" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Show full side-by-side diff for this file" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:38 +msgid "Show inline comments" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:62 +msgid "Show file at latest version in this repo" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:64 +msgid "Show file at initial version in this repo" +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:4 +msgid "No changesets" +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:8 +msgid "Ancestor" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 +#, python-format +msgid "%s Compare" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:16 +msgid "Compare revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 +#, python-format +msgid "Showing %s commit" +msgid_plural "Showing %s commits" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 +msgid "No files" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:63 +msgid "Mercurial repository" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:65 +msgid "Git repository" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "Öffenentliches Repository" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:96 +msgid "No changesets yet" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 +#, python-format +msgid "Subscribe to %s rss feed" +msgstr "Abonniere den %s RSS Feed" + +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 +#, python-format +msgid "Subscribe to %s atom feed" +msgstr "Abonniere den %s ATOM Feed" + +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:6 +#, python-format +msgid "%s commented on a %s changeset." +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:9 +msgid "The changeset status was changed to" +msgstr "" + +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:4 +#, python-format +msgid "Hello %s" +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:5 +msgid "We received a request to create a new password for your account." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:6 +msgid "You can generate it by clicking following URL" +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:10 +msgid "Please ignore this email if you did not request a new password ." +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:6 +#, python-format +msgid "" +"%s opened a pull request for repository %s and wants you to review " +"changes." +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 +msgid "Title" +msgstr "" + +#: kallithea/templates/email_templates/pull_request_comment.html:6 +#, python-format +msgid "%s commented on pull request \"%s\"" +msgstr "" + +#: kallithea/templates/email_templates/pull_request_comment.html:10 +msgid "Pull request was closed with status" +msgstr "" + +#: kallithea/templates/email_templates/pull_request_comment.html:12 +msgid "Pull request changed status" +msgstr "" + +#: kallithea/templates/email_templates/registration.html:6 +msgid "View this user here" +msgstr "" + +#: kallithea/templates/errors/error_document.html:47 +#, python-format +msgid "You will be redirected to %s in %s seconds" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 +msgid "File diff" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:58 +msgid "ignore white space" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:59 +msgid "turn on edit mode" +msgstr "" + +#: kallithea/templates/files/file_diff.html:4 +#, python-format +msgid "%s File Diff" +msgstr "" + +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 +#, python-format +msgid "%s Files" +msgstr "" + +#: kallithea/templates/files/files_add.html:4 +#, python-format +msgid "%s Files Add" +msgstr "" + +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" +msgstr "" + +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 +msgid "Location" +msgstr "" + +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 +msgid "or" +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:58 +msgid "New file mode" +msgstr "" + +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 +msgid "Commit changes" +msgstr "" + +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:14 +msgid "Previous revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:16 +msgid "Next revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:22 +msgid "Follow current branch" +msgstr "" + +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:29 +msgid "Loading file list..." +msgstr "" + +#: kallithea/templates/files/files_browser.html:42 +msgid "Size" +msgstr "" + +#: kallithea/templates/files/files_browser.html:43 +msgid "Mimetype" +msgstr "" + +#: kallithea/templates/files/files_browser.html:44 +msgid "Last Revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:45 +msgid "Last modified" +msgstr "" + +#: kallithea/templates/files/files_browser.html:46 +msgid "Last committer" +msgstr "" + +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:25 +msgid "Edit file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:58 +msgid "Source" +msgstr "" + +#: kallithea/templates/files/files_edit.html:63 +msgid "Editing file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 +#, python-format +msgid "%s author" +msgid_plural "%s authors" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:8 +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:11 +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" +msgstr "" + +#: kallithea/templates/files/files_source.html:38 +#, python-format +msgid "Edit on Branch:%s" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "" + +#: kallithea/templates/files/files_source.html:44 +msgid "Editing files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:61 +#, python-format +msgid "Binary file (%s)" +msgstr "" + +#: kallithea/templates/files/files_source.html:71 +msgid "File is too big to display" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:5 +msgid "annotation" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:24 +msgid "No files at given path" +msgstr "" + +#: kallithea/templates/followers/followers.html:5 +#, python-format +msgid "%s Followers" +msgstr "" + +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 +msgid "Followers" +msgstr "" + +#: kallithea/templates/followers/followers_data.html:12 +msgid "Started following -" +msgstr "" + +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:30 +msgid "Fork name" +msgstr "" + +#: kallithea/templates/forks/fork.html:71 +msgid "Private" +msgstr "" + +#: kallithea/templates/forks/fork.html:80 +msgid "Copy permissions" +msgstr "" + +#: kallithea/templates/forks/fork.html:84 +msgid "Copy permissions from forked repository" +msgstr "" + +#: kallithea/templates/forks/fork.html:90 +msgid "Update after clone" +msgstr "" + +#: kallithea/templates/forks/fork.html:94 +msgid "Checkout source after making a clone" +msgstr "" + +#: kallithea/templates/forks/fork.html:99 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 +#, python-format +msgid "%s Forks" +msgstr "" + +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 +msgid "Forks" +msgstr "" + +#: kallithea/templates/forks/forks_data.html:17 +msgid "Forked" +msgstr "" + +#: kallithea/templates/forks/forks_data.html:42 +msgid "There are no forks yet" +msgstr "" + +#: kallithea/templates/journal/journal.html:24 +msgid "ATOM journal feed" +msgstr "ATOM Logbuch Feed" + +#: kallithea/templates/journal/journal.html:25 +msgid "RSS journal feed" +msgstr "RSS Logbuch Feed" + +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "" + +#: kallithea/templates/journal/journal_data.html:55 +msgid "No entries yet" +msgstr "" + +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 +msgid "Public Journal" +msgstr "Öffentliches Logbuch" + +#: kallithea/templates/journal/public_journal.html:16 +msgid "ATOM public journal feed" +msgstr "ATOM Feed für das Öffentliche Logbuch" + +#: kallithea/templates/journal/public_journal.html:17 +msgid "RSS public journal feed" +msgstr "RSS Feed für das Öffentliche Logbuch" + +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 +msgid "New pull request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:44 +msgid "Write a short description on this pull request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:50 +msgid "Changeset flow" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 +msgid "Origin repository" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 +msgid "Pull request reviewers" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "owner" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:114 +msgid "Add reviewer to this pull request." +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:128 +msgid "Detailed compare view" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:149 +msgid "Destination repository" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:4 +#, python-format +msgid "%s Pull Request #%s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:36 +msgid "Review status" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 +msgid "Pull request status calculated from votes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:56 +msgid "Still not reviewed by" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:60 +#, python-format +msgid "%d reviewer" +msgid_plural "%d reviewers" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:62 +msgid "Pull request was reviewed by all reviewers" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 +msgid "Pull changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "reviewer" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:133 +msgid "Add or remove reviewer to this pull request." +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:137 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 +msgid "Compare view" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 +#, python-format +msgid "%s Pull Requests" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 +#, python-format +msgid "Pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 +#, python-format +msgid "Pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 +msgid "Hide closed pull requests" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 +msgid "Show closed pull requests too" +msgstr "" + +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 +msgid "Search in all repositories" +msgstr "" + +#: kallithea/templates/search/search.html:53 +msgid "Search term" +msgstr "" + +#: kallithea/templates/search/search.html:65 +msgid "Search in" +msgstr "" + +#: kallithea/templates/search/search.html:68 +msgid "File contents" +msgstr "" + +#: kallithea/templates/search/search.html:69 +msgid "Commit messages" +msgstr "" + +#: kallithea/templates/search/search.html:70 +msgid "File names" +msgstr "" + +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 +msgid "Permission denied" +msgstr "" + +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 +#, python-format +msgid "%s ATOM feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 +#, python-format +msgid "%s RSS feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "" + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "" + +#: kallithea/templates/summary/summary.html:4 +#, python-format +msgid "%s Summary" +msgstr "" + +#: kallithea/templates/summary/summary.html:16 +#, python-format +msgid "Repository locked by %s" +msgstr "" + +#: kallithea/templates/summary/summary.html:18 +msgid "Repository unlocked" +msgstr "" + +#: kallithea/templates/summary/summary.html:76 +msgid "Clone url" +msgstr "" + +#: kallithea/templates/summary/summary.html:81 +msgid "Show by Name" +msgstr "" + +#: kallithea/templates/summary/summary.html:82 +msgid "Show by ID" +msgstr "" + +#: kallithea/templates/summary/summary.html:99 +msgid "Trending files" +msgstr "" + +#: kallithea/templates/summary/summary.html:115 +msgid "Download" +msgstr "" + +#: kallithea/templates/summary/summary.html:119 +msgid "There are no downloads yet" +msgstr "" + +#: kallithea/templates/summary/summary.html:121 +msgid "Downloads are disabled for this repository" +msgstr "" + +#: kallithea/templates/summary/summary.html:127 +msgid "Download as zip" +msgstr "" + +#: kallithea/templates/summary/summary.html:132 +msgid "Check this to download archive with subrepos" +msgstr "" + +#: kallithea/templates/summary/summary.html:132 +msgid "with subrepos" +msgstr "" + +#: kallithea/templates/summary/summary.html:163 +msgid "Repository Size" +msgstr "" + +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 +msgid "Feed" +msgstr "" + +#: kallithea/templates/summary/summary.html:193 +msgid "Latest changes" +msgstr "" + +#: kallithea/templates/summary/summary.html:195 +msgid "Quick start" +msgstr "" + +#: kallithea/templates/summary/summary.html:209 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:299 +#, python-format +msgid "Download %s as %s" +msgstr "" + +#: kallithea/templates/tags/tags.html:5 +#, python-format +msgid "%s Tags" +msgstr "" + +#: kallithea/templates/tags/tags.html:29 +msgid "Compare tags" +msgstr "" + diff --git a/rhodecode/i18n/en/LC_MESSAGES/rhodecode.mo b/kallithea/i18n/en/LC_MESSAGES/kallithea.mo rename from rhodecode/i18n/en/LC_MESSAGES/rhodecode.mo rename to kallithea/i18n/en/LC_MESSAGES/kallithea.mo index cd21bed5d53e0bb9ab1f492b3b051b9537763722..dcd4d6cefda3d9e63281fda0398027c30805584b GIT binary patch literal 76366 zc%1FMd3;pG@&`J&A_9tDK*Z$;gajo4+^*tPWG6}>kN_f^Co?CLfyqpqGm|hVC;~3H ziwX)VAh;`=qA1{X1H=u)1r@<7E`TBkh%BP7s=sx%$ppCG_kMr8&-jtl^j=+EU0q#W z-DmwtM?K)9{~8_T^PNWUea+|j@A{5DUtNNu37$i6BEdX@3kfzO_&vea1Z#H!ynx_Y z1WO3g|Gx3`rxC&B1nU!APw+&7TM7Py;GYCfB6xCVpYIfcEjuH=LuceGCRm4{(HVGD z2pmoDc*aM<4+?yoU_F9!JEPsD1e*~2RMNK*tWEF_f+rI^x(nKA(gpRM-34^GunX!b z>Vo!lg2xgJ6Fi1sT+**2cqYNyx}e`rcR_#N>w@~%6J(O^AXvuz?23A>CwL{(hu{=~ ztGWW;P&eRnBf-W5@9hSBpO*Of5`K$d10Jt#pxb(aM-%+L8}K_o@NR-fbw~Jqf=3dZ zO7H}Nk97w<=5)unEbb1vztsUzR!0$!L#y_uR}ia^~wjmi}TU%l6=$` zm+`!AE;y9(>so{XV9^=gTJ8j^G6Z2Ns~*-2~eZTtqO7=~w`IoX`v9&n0*+!J)m7 z|K47hSFiO#xh=gge@^X<`iJyJ`h?!7=f&RW|L47d_cy)K&tC=BFQl>r&nZN{ZiOh< zo8WN-V}+pa^@X7S?SVtOjCBAPT zv@?_-i56d3AJkhe@o~vNrVr-JEd*OIzexP+eZU7Rq}&ezxAs9lb`fmHc=QEb^8126 zNA{KZ(^uwCU-a|ozL0P5Q^0DQA!0O)qqRR}k{ z3V38+h4#+B3geP5>7`d;9*mTHPYHZU^1pc%#`AN6A%c4dHYZpz5cBQkfso734aEF? ze<0|&b0Eg2{?(xWKd%Nq4Za$5yWwi!G2?3R-_onWXX~y8{`Ci8KAt%U{p>Dqz##BP za1i+UItkx32=ig4Uz2-VGeK=4wYr$a!``9naT zwL{R}z9HbRBZs2CIz!Q3qoHWO`B2Q8^Cf)cQ1o~3Q1mN06!_dZ6#aOF;6(%%NPRy` z`8`tpgkh*(8wUQ!9fooph9SM*FyK`>415}u@GX-6o?&Qjroj2b!2fR!gB)Kq4EXIQ zm}I(N1Nz*04d{30H7Gav8npYQ#4ou9^)J6hothEk+IUy64AQ!49H5aZK2 z2tMi*ME`pQ(eM62(7h@My>Ptbe>4cXz8J)~uL@$EJ`G}=HwGa;wgxdzYnOrUCzoMd zFD?^(h2UM>UK#RzU54_T$}p}w%Fy0ki9dma*9!!jgh2NdA<*~B5b*dlg#PaiA^#b} z(Vv{*$lrE2>g_aK){Ei5Cm{KT568I0hGRaA8xFeMA?Z_wqn+u)LBH9<(eGCYmNGt4 zUz-u=-vuMkUY8NT>&g+R#~guvT}N>D5wz}(K)G8ZpwnFu(BnmcuSYNrDDIcXS+hb&sPTSI5!MYvLHkYvZ8j=s4(dYaHWu zUmW8#UDD@B{Ht-$cZH;{mhd-m^n0_^`&S(J9iKpXErERJB%tq{pTKyS3CNX^35?^d z3H0Y~3C~E#`kg@kUrK<#mk9hM0la@op#9$xpx^P8q&pI9N3a9Idn$qds!ELC`by;A zUx|7fQ~}>60`scSZs#iCU05ahxxl-t(64u@(Eh3_(DlnI^yeo@-(Lkf9WxT?4M!rq z)lUUyuO1YIu;ImfJwxm~YpP#=fyi(%&DA{(d?d?R_^Iblpd=J;C~8 z(9irapzAeb1aAo^$DqCOV?f^r$AC^V$DsZtW5B=5#z0PdH3sYIPRV!r4Uj(<-GKR( zya96JMhU-p1L}YG2K4VMfg5iCJ$||Y9Lq63&&!7*N%mLuz4)> zoO(B59L~83`b77eK-a39K##j_LjG57f?QsA6Y4*99LA;LIE>3V<4{kBaY!FD4)ZNE z4)`X=$^0A#JnkO{y3Zab<1r5SFOz!Lj>Gu;G7kKE&b}4&>2NE?q0gI$MbDiGKHoJFc-Ffebk4dR`fJbI(XYhqpzFljQSRy6(T{)Mj&?q|9p#U^ z1NqJ(NTSbo`5nmj+8yA}kM4ln`T7pvzfsb6-GO;k`%dI*b|?6zEx~RCFP8Wl@5Fj` z*PY;_DR+VoW(k}p`Ig=ZetloUs|j99dfSFO!FPS`LHk$TgZe`EfPUsZ=-*xUp#IsC zZ{9uFFTQyXsgfAsXTSeb>_hP<%aWC54bT8<=^sYxgY$o?S9aat?i6Y z{RhBDnuNPQ0KI461CSdxJOFyX^Z@v8)dQ$!^8=W-e?9;XGa2;0bTa7IXEOMp|76rVM9M`bqy0+B|KMcs>ob!< zuep;kFJF^#KT5tmlhL2LQ$)X>f_ZT16wq_<6yPyx3g~?66!d%M6wvcEforEguKXtX z8b1Vl+C7AR_jw5El@Fo*DG#CkmmdOueEJajam>Sj^&dum8$FEiY5Fk6KkH%eUAu=t zhYKX%zaB<=9Uq3BKz|tY|LS4z*Iy4qJ~f&OeSYXvA>UM>6oYa5=)Uk?z~dumY^p zp1^pW^907P4Z&*(7CZsGUVj4PvE~W%`^zW5SHC}jd355F&`VDtNLwb~z$a1P>L*d( zr%$4tolk=A_C5){I_D|y+vumTUOf90^p4F>;rt`(X|z-JG{R#Eb|Luo(~vXAJ%e%= z2sEDoz2`lH@%{c8=wA(=h5fzYSrmp_Mb9r+yi zaPo6<&PT8(!S@LE;eJ04J|F%(#wGqd`24QtQQr&CW4u3kUd}zA2OUp-LGczh%Ab?2hoKjtEQ=3KOwJs0cpIdf6Z zC3C^Io#uj1ubc}x5|MJ|T=2(r5`J3XJgI-tT(tkTz}0hs=lZ$m$9HoXR zLp>+YL%F8&AU|^EL7w!PCw4SRA3jgc0q21(kIuvTHdn%LNPTN0{M9`4YwJAGBjy30 zTJw>w-h9;Ga6ahLbUw**qx?VTgRd^155B%)KJXbcA9T8XKI*@RAgOP@sZ##Y z`DkyJgy+sjzZT91KfF61QiwHKhCQx^a)Z2|CVwE+3gTY!4n zFM$5nVFAirzX0pfU6Oyf#IIfeyf+dYPVg6kH!**{2)x(52>dp^h<5k92)zG%5$)7_ z3FCRvOGwuUj;Tds^b+u%y%793e<9?}`i0=HdM`r`v=unyWz6S^FGIdO_cG+}wwJ~3 z^NQGgUcvln`3mTG$t#c>y(B&;`L2Hj{kroN;4wwu>{rmQ`4V0#@V!^ikF~F$-5*|o z{5T-#jTeF5Ef!(^=Pp7!9T&+t>mtaJp^L;HVG-KDZ4vnF{zVv{X_EfgE$xG4iCQH$e zwo9?TNqD zgY8nT{&K*E%h8Y1mg5|`!*bB&+U4NS>C0vQESLGST5F<@Ye3-hL1M3Ln1*`gMLEcwG5D^zdumNBQgD7d+mF-aYGmvD*s# zPT)?-f5Zo<@1zgFH>Z98y0w<@r5^x~-XEa7!5?5;u9ft=KEOPfF8Njo{95vF`9RKH zKY+i2_96C-6F(IF@I%PuPd>!_-Sr{p+4Lif&xId>{=+^3KaKwgbbIn6;PLK9;J+U} z0-qhV3iw~R3iGl1D)cid@P<|3kGofapC6a-!c~|LD<$7&690qb+qX*em(>{0hO5Ds z+G@0a;cARS@oJQ>5O|~HyJxk`qt&Q)&T8QK)@sn}lhxph|46x?Rs)~?t1&N+{TThP z`!UM5`51QW&L2bnpY}26`Q^u;k8cgyYqkdbbvY@9Fs&*0J%Qq1}m+KIJpearS5E$8!>1@)_vx8wyzwuh&m%SGIfF5gscja1?n#fqDCo#J~Fm=H*`kn|}#0&4&%OO9meUvI*jx2UqgO0{2KGL?bo3DC0}D)^{+)=`5OKTm6Gr1 z^(cShdW`F->(Sm>693Qj@K@-#9(3Qn9`rq81Mq0F0sTK?1M+vn*Xpx)sd zWWCq`eD08Z_iezqJ-h+);n@wK%Zrl!Z)s=6204GY4ft`t|rX@K;#$jqH;)f=&xJf*$Jx{ zC*dC7fer=V30~j9Ut!31=;!y}fiAnhL;bbCmwn;)nBPsm2jAv>4}XO#zlXoVMoItI zkLXA5A5o7XuvL*{MYdd}Vqy3E}yehHf~UMnR1 zbBX_UGw8cr()UWZ_7?QJ!4}k;y#@H4w*}>UY>{*EEzoxcZ^3v>-2%BXeGA5M?iTdt zWeLB#Mb_^v=>OMSz~A2s{9_C7KKUoKfBH|L-+4d5zB}+I_$$2f6Y$^jllYtbjQq`i zM!gsR417BZ?Ef>`9q}{p9{IEA=K^2;S^NWkM*Dky23?QXivFCu73s~lf=+o`k$$P9 z_u7hjhi(NOf?J`Vg|}jzoFM5>ZUsH(ZUtQyZw1~TZbg5-llpc@_=sQ7-if~e|1*C9 z|F`}H?RWbH%1 z-zN66ZNR(3Hq?LRHjG#CHsCR0o7f{H|6SXF=Of#I-^<$|k3Numo22|c2{+gdx;5X9 ze&%ckUKebK-LUg^jO(cFXzwOTpR^rz?-|?Sudsc)oFDv(cJ*JeK2-fGc7k7FKbik4 z&JDNyit%r;1NC3ML;T-&i2wTz%-hjBFy9{9fqmm+lD=yP`g>pp+N--0bZxd1{t6fF zL_e?H3A*08Q}CAXjGbujxt(Hv-YNFyov8o&opK(&6LR9nU07F}?n1tj?cr4xnx__`o#$ylg|3&Kc?Zx;s+6(?YXD|4#t%M8rihjBmd=}gb{qK>z==Z04 zQO~z~LDxNd(T;B)+COd|@HurK#y?^b^yzWZOOx8yI#gBv9M#lL{p$A5uu zzxzw{Twg84=cf^5JTD-~bS@ys`fHpZ_v;aYOxO7Yx!h`k+>cEJxt%|xe7jo6mrs!W z70PNM-$sJWpT84ixpVXpwG{rxAA$7K2=csYdj#@bL6G_8DuV2%H0u9A@_j*& z_lsKyvb@bX24RCB`zt(7kmp;iW6|!31l7HTV?mefW6{431bI9M9*cg539>$PBSE(F zj3>zc3JZ=!|6A9VaUsZdiGtdwe+)t9uW_}}&ZOGFdvwy3E)ImKBj<2QWZA*g6ANF|QUvfOg;bww7-zF2}b#yU7 z_E*?RQ0Yl^0Xx>kxaSKTP#5$z>VkgBy5NH`by4pGDfeJqwEw8&Us@OZ`f***Yb`;Z zmm8(r3H6XqtB3xaPf+RC^)L^NdZ6d{dcb35JJ@k8JJsX9SeoknB@qDxa z(q9$$X#>=|UEr}NfqrKYWchpkN$7WkAlpwSorH0J|0M9&ktd`6vkCHkuJg&D!!svi zK7B=y{T1r`qn7elc#Ri?=S#_`9-7>{#L zLHUAHP=83mH=ly?GfxpYa0<$=BFJ`%b*F&tCpN)6>DUDFp=T4wugWIC@2)1me`XWV z`DID}unFq>p$YKV(FFWc?^MtwTVUH$G42S7)&uxl!E^3N! zK~s!ZQB#cH0D|nVkZ20Ler$^I*xwZWKH@a+)tRSZ9$iH6avn#5?5{BPG}O2EG}L$C zG_=$7bnx9-1X-^xJRSTt`*f@qYY4L5(cp|)>inbN4778Pgr6qJ{t7>z0Xfs|Oq3fU zaO#<$_ZMekeCuhol>T)oLAJjqG|*)xLDn0WYp8#RhIw=RS&+k>&O*7evoNmH&jKI5 zeir1*YJ%*qu#+JBD_q_Te12aujLWoU;PZveP~T_GFy4PO1KnFT2OTeI4t}|+IpTxO zLGSA&d{1-WJ6qycN_c&9@b!@`02{Obo@WZYtOd#sX@UA<5+2(EJSgR+W`RE*m+)$VUr7D`$wK=-3*4IpJdbIKe$;IV`kW%LWlOYs zeoNGINlTRL+!FGmuqEV4vL))dL(=bSiFx%{OVDLmORR5eCA?Yc+b`iGv(c}H*`h~e z1D{se$ag_D>c2D_bm^Rpa@{3=-2ve@WZd!7zbaD=wmscOGAOD<)EGBIl!xJ4(jQY1H5|V0Ixohe~{Euk^}uO zDCK75U|m`$`L{{@-W=e4e5+c@U!f5}_E#9&3V0uNHt;*~Y_zML4ZK^Pjdm_L8{^qt z(t8l}X?i4}Wtm!eG-mj+auTKyYh`NwXnDC2i5mee8qxe^dL(F=MqJb5T2@X~nGtDa z){wU%5e{oH2p-+k+`W)i$|&M%1|m2&9ibUV#7j#R%Uxm{fvj=VS}p(Sfp_M zRM7!FDL@6wqKTLVRYZ9xl8775FGNNo@iO~|iUK-D%>7#>n1(+Z2{^x0WYW-M7NiK1 zN4eB60{pXMaqj{<&?y=nQLe{Es7#$=dcXnbSX&_yj-gY8@g#|u|!0rP=(=;U*~?%=;<{1>HlafV8now>DMC; zB0_ea}~MSaqlIwQ2)Twlk+d~Jk5(_2lf z;WV)$dKi4FVk#0PglkGdNi-4nb@X!w6sRO3FzPI69XY1@a&00MGqj?jo@zWQ5@s1s zH}#Y9MS^)+eyK|K^GKI6Sq!FpdB`+5ClflPMm0_t5aK$m zas&x|3#zeK0mT^Q(MrP>drX#i8THW3ta(=EL`68N2V^<~h;;sVIH^^Jbce1gYs`yz zEJdD345*o4((hvztG1n^fg%Joo~ClnR8@)|(8I;y<7Rk$*1Rb`>L5hejA zsZ6gj666%5MFf9c=y0fl7CoMGMmdwZlH@$&Qd&yXF_c(P^zwBK64Aq9{^zU)9LO)! z^gw_nmPys<#E-g?;sKSY`ypYI8TEA&GKtdq?-=O#Z6=EdP{yUsp!tei{STekyEhNMT_Jj@iSHn z(msee^0bbTXe3!4O+Z$wznUeuU42E(*5aop2xVF!{M=MDLAsv~IjcmjJ7>8bN$BAk zvytY=1Sd&KGa$tAxzI4F@xQr5+9i zq@5b`D(#BtT#9yT&T6geoRw6M!^-CxI+IkU!z=}Xb+|b#=~q*Jh(c4Zq(IHNNB|xx zi<|2YnV03b(ldB%i8HJE4>1&K5u%Yl^hmg<$~po^9c(~ok%_8IRI}5En)8dQQccRH z5u-I#p^B2u7du3sRX&sU5F|hjBYPr3WE=s))9fa!e9qLxg!gr<2(h-LnF$pxrGZFV zN?`g##ZWaRDj7ye6*1BfC{Kdsv!%O#FG_<`o$YkYvesatuUMjhFGY0 zql+v>k>k08E-_=t4IW8jB<)Khj#%+^tRy~X1xqVQgu?M$9xkg1JE`0#FX62b#l&gn zrdHZO$mFzuuTvlmh%OGMXsheO2dBwg`!t|ru6R7a{wfY^dV5#AN(#OFa# z7O*hUcA$cKOvI8b7<#pjiIarlWreo5ankpRH1Rms8c=i0v`VPSWVlx-R+^K%+cv_b z+=8xjq|SN;byD|XGpp%}-c+X*;n+P`FeXeZ-ePbGMynzu;b^#1CS#tJfm^m$mI~@} z741^Ii78FcxC4OA`f8HA5t?c#Y*BX&YQe=G^&+^g0g)i{AiJnmX@|wD>)km*fON{lf>*5 zVLb_YDwDxs)s&Z)=X2R5)K4WV74F#2yG&UQ;!qVdZ0@|>kj<;5=yonMxbKV?<4Gg0 z_8BZ2X}5%m%tVPAEM#T`O4W{p#gGXcDV|jvlZM_;d{;_Rf)o&ySD_Ixd}_l*(?HZI z3M=&tbHtJmooPeN+t#pwO(ce<%!n!7T6gcF>`^nLG48zIhy)Z5d*TB|^#lm?JZ&It z_RC4*VR1{$>fWNd_ubSF!&)f~qv`7$4Ttp# z;ZO>dm+RCql2D3sc>krAYzXl@t+yhB6T=Lohs~(ahX_UcHj=w;eU}i9lNjd_bCwwc z8dhg9C<^pgW8IO}=bofhVEbx?m5LG3*qotV*KTy46|aOY6EtB$Rng2O$=H#$4arPY zR1k-t014s(*ifyYAY}#1y{QsZ$t>J0=(0T8G4_B;L|?)mn!OdnvfdN0kW3RPAXKv2s|fZ2>QlEGe*tscE5fU5MB8 z8Ppu-3^wuI!vDW66EbRS$;~x2<#F0R7|zVBsp+;NV7N6@wexXjW9d>u4;6mGS{_ZE zjmhqeVjNPMXauX3n0~8gQuyl7BU4e9-S9zjKpJ}Stw@T>BI4P-9Yw06iKxYzdm<%L zH_myfC8|{+lwck=JQgfvg*P12oGaX&?L-nTjKR?8iNl`38|4_@tvJj){AN}Uy7GJZ z4ROxa&x#6IP~+uFetOKy>0{C7^r;}aD~;x7dv{o&ks9`vQY&7XQ;g2SQO=}>6+~&l zzAn01Rua`I+WsZxwJxO3VS|*%zYSj(F`LjH*0$U!#ehvK%A#RsagV(fXNf3P1ZGXP z=C!tU5RzEDwbA0V=dgBbp-8|Osk9_k*2@hoXhf|2+kaDW74_CEb5&%QKKL%n%9U!P z(P$dRl-!gY+)tJz0-&*2zm;a+B}LX$ix3L~qG8N*6%2@AS8QQLseKb=^x9gjROW4W zZZDInSf$%3l8Jt(_CuOdUWlS-lGHIhV3U~&(%vdmA!9%?DuRuYi|05x7ENl=FdrGl z871E3*d3BBkE@Hc8KS)*Yy8fV)P*%_5?FohmaQ#hmuMuLw+JK)Ng1;CB^@XpBX0jt zhdrk1uC3{sT3@}&6CM?+aKcJUvO?aitKzVfCB>E1-r;uTzQR7nz4snKxlNva(tabB z`YzTCY&w-fYy|T7u))^WV+JtfI+>OIN_j>@d~}oN>lz5f)gK5#^{db^#;9<$!wnUy z7*_qF=Apv0C$e!&jf}>L%t0m2F5bJ@urk<{{~dno%Gw70Y8_#`mk?=&rJ<1sa9l+^ z=^mM`5grZ!&Q?e5(bUFXou?{ck(Zjwv?9uav>T$yt|SawLn1&5sbM`9G|-{yX|&4n zv9X+Qag$gdwPM#u+lLB#6bO4U%Tp-*Vu*&=a`6wT<*Yu`+>m<<@5;q%galm*Mzt71 zDnf*)iAVtp+Qy}>5#Il0<&=jatwOBs#B}1`m{L5|*(@^X8mUtWBV9(?J_S>92OK%W z+Yw#tl}Kco^D!&$MiFC{@%AsQml(t>%C6_PRztUvsN`o#x>qnF5%yfQ%X3G>41cI1 zq>K_>)0?{0exasBmmNIa@_*=3mLhPNIS)~D4My}slv3-8)l?06Si3k>9uxa?uMVF+ zD;8%)GhnT^hstQJeuv8E)>RIbHyxuKR_;Sk)G2fD@lDD1-_>d>fCtH~>^Cl_1lynB z5M@YICupZ+rj{DX0>v}KI#6VVTD-jbY>8E?FZ~XYm?vl%pV`=*=3t95#6&Kbo`Bcl z+zrZwvw>2l%8?TwJ@qT(81Wo?ACg!uAwU13^;wy8OAHa) zB*}1|&udgSbza>KOQM`(BM65P>p+K>$e4GF!V)h*3Ra1sPWD(?=&0;)e#>mA^ahAr z-L`pQF;Si+%HZqS+Ln^W#)4Wkr93tQd4x`krcy8J3w}n_FXjIvz}~iE0rxr1QQe|! zAC$ExWo6O^M3r&E)&TUBQx+}cC{?s-#zH{@2bd5UT&w5ks3d7Q7GUFT1X`nZ?xo3N zp^~}lvI(XVfv8ob$%w~-QD?72Dy76I8@D%lg!%(5lvtp|aGK$B8P_p@$|qE#U(r%P z&wjI;+6)UwbyrdvES$``@h&pI(AOh>@Y(SzcTP^ih0=O16o|3ruOuTES7l#DkGD}1ap7lIH42-Y?c2An>|NX z!02v!_EqPc{{e@H5ht0Xu%Mq+EFmoE-$oiLi^5o6(?I&Lp;LdgW?4B(K^Vr8r~b^MGtKSgkLhv7?k+Uec{WU4A$?(1O?yR&fW!TS;ZlkN<^;b#b5;eMNEsm3v4>C=~8H2TWg~l;w_bt zR8?8!3zP9Owh1L7Rz)$_VYV}1v}w-g?o!7>70Tr>;>#~&sq5azQjFuRmhWd>F+Uig zMHkVUSwXYemtW2Y44`kyzM_LKpE|<6pSs7dN;fUX0I`WWOFxTK`@9%q#-}fFu_}~s zWq#*0Pxh014yM-j5;LmoOUhb6AXFSxHhM$ z3IvN=%Zv6K@|}Yen5!(iu}25WKge-QzRT+DyFxsJ9Qmi*Ln$eyv%8KH@7l&Yk(PFJrD0U4 zDW*&ZJTH`kED0&n3FEN6=~~~e9lI2Cg$az&W>baNJV7$#N+ZetG)v=$-pPVO&R1zJ z@~E{2tD3axvxQnMZ!s;Bz-c(u0292z$e$qQ=&1}EJ#}oAZKGIEovMYa0Dkw3lFE;t zN~Eh_eLdMNxBeJ{VW&iSlr}aYl5-r2pm?0mVXZ^ao|b~xQ@Z1a1y^k@D48@oMvoOr z>$jp8kCrPEKgChW`hg>Pr4)sAcG*^HtQroL!g5&LWvBtLI;pu-e1!Vr)*(5}-B7@r z5Y+M`0(h9SOcm&zh%1O4vO28e19HB9;)2L?xiTW^8i7;2eHiE}!QMkSU}m$LNON1KQ4_3yJ+Cl7 z^?(WqIb}Oyl_n|{C{GR!^mCn+6^MU_<8{^5vX8nWT_aRr#P!@_J;*y(Ujgx&a&9XS z?|U%NpT(6lcEudplj}3wM1J5Vv5X9gjzHNu_4Vq;XPcGTh$ zR0<=9jP}+PRIXKKB4+znscnrPhj_}7UQKCILZ}$`+=A}Dxo2aqge85{skLQ@!%a$c z#maSWBp3??SaU38#hs$8lgp5@rBy}p4qaWjF14w(8;kYfRTz&F4JwTkm8Um*Ag10D zO&_aP2J2wZ&7{3?>#Zb7+(7|heAeg&nM0I{s)Re-w%oq*w*64)gEYE!VKhU_geduJ zPpiI=u;%L&O8$*fggounLY~9p-qz7N|EOZc*x6CpmgU~;vFa;ik1xKDOS6z&nk)|+ zyDhi13sOyKd89outI;M)DewMhnC++HBUNY#H0uX(Hv6g-rj>1WEF5pbp~#4IarQFJ zhaPY;l&S3%(Nri1Vq^{kH(~-~PeB=(8@RF4S94m!g{c-*;zS^?e%(GnZ-Bx_ngIr-IFE|#GJ<;Mj?$^WqL|C`243*Kik&;t6qQiOzH}Et_aUN+%bsBqwbPcD3Y}zBYqZIP=*ZYx5&T>H+nq+z?vE z64jgxB_>^Z%1Z1>v+aYPSbJW0VpA`Z@tHG=dKUP~r}`2x`Kpk&ta`&F=3D|wpIRmQ zij$gj{p7<2rh4^b23DMdp7RLGlcuD7N)ciW-LSn`_zahEa8Ax}c+NtK&y3*(jO*-yO zyhD*CnhkE%vbdQidGMZAON2}TL%X(^ESRcIyR;RhAy#VI|J;TuA3Vs^vv0JfiAqZc zD=iK7)zAnYM4niwX{3pjlvb8F4+K!pl#RK@374i&4KxT=V>Qd)um-7=RJZbIc1BW| zR_>UEVSRNaAO_lzJ6?6c>Vf6vA!ltV*#b_!nmd}7o`;xzH4qw}A>OPWvLEzN)m_L- zcJKQqm44UFWjopQx|@bWw9mu6DtHg^p^)6G@tgnc(k zjdG>g%6gUqROKTz<)r7i6BmQijqC1bQ9*H`qqQMKdp!J-vvKvCoj+&{oIr8UB0CUM z%S92@t^PRHh9dT_(ABwzb*QG!cH*&wACfDWr)67i8137%xsGcaeYtg}-{v|Vm(kg+ z+2us;NLP{q-~NAh`S?Hf_fY+!AC|+H(!eaz{lDP+@OM2Q{)eX3(9n<4g!?=a!smai zHWV1G<#+M=g0@cecwlof^AUK99l1lq!f@&Wz%yig^kzkbBF?Ys=crCnx@g)ll-s|F zo_-}5i(tD;aV1bP*>f0ct+Dnol~T|Tv$VC09)4lhLGmG*=G%HWU9Wc0EX(x1sv*<5 zwGxolYcS5!K+cXLPiluSj*OsSB%uCyFPEtpY+B;FIl_JjLd92jt$`{VQq&Qv6pK=n z;&dhEBYs0EhD8Qf&UP<(y9Sm3>oEY=G$^v%4mi6qjikOHAU6yA*0pTqmF0<9w8N|Qh&6L z>_ThTQl%;H#~vY5Z9`N{_0xS7?Xmu-R+y@sf@3!P)^YAzqRvBH2R>P5?qybfxi@6} zj#s>T#{CPu2V9k9b$BoyaW+ENBWt_P{SIm0-sKS)MyNm)3& zL5J$fjOQd)d+{(`PCO~+Jkp>d)%^|i%Y8J37&lL8A%FF!pd_37h}0c(SmoMSt#C$C zOZiMOo^qC@9JKSSQt6CTX_BDEs07-78kQqETO}pZIapyALcEEfyoyzN^^+TI*s!9S z(o9a&axWv$6?xo_W*i}x+~vMWwHVWm(zUWg(0ZRD6fBG5IRlfu@z|%svg)Y$fMUv9 zu8ansjgJ;zMeL(2XRcK{A1jTLCK@B!@|!665x{;G7PP3yUEwnf^-cqaa;uot9Jd#> z>9wY4>VbF>ALi;LM3qB(sqJ!`dNr>|e3qRYxf~Zae6E)@ou7xk>&JObEvT~$WK)WY zNLbHR@^EFDDRG|X4vLg7pFHql*-$AqT5-@`B*UT7q&lDtk~lR2&Vg5ZUs0ljoqEK% zhC(b;OAHX2qyzgDvXL`2C1#pdg8Ky{`{hp=s5CDaS(gFRCwk5?)8@dcT~mter#M15!48P9&NNLnptOxlYlTkh9TFe&-t=sp`jS=gN%2!N3dUokp2tO}=HHgMC5w|^+ zJNL5PsBBjUEf*Mu)aDQSSIO>_x1F1516rwvS+3F0H?vgwW~$}XXM}K6AZHh(x)iHN zllZV#ECK2?P(@n`y^@JJB_x`&0R;nKR#6+E0 z3whv6M@y$NF}OUk0|^6%tYJRbWNV*#3nWjfl4ol?b;0SP*r~&aD6by%EVH^XV*7vd z`@|u+mBVN1{6Yy{)U|v&iKA$igfX3MmrIhhpdO!YA9$XN?g}$YbeH8cr+Rev%L`J z+1ZrWxSWP7zaIBxU%uYXwJIaMylueOc&tZ)tr_7guzX6Aky!LL{7>R2?y z%1m*JmxV2^ zVWw&n>g~Bppb`btTLh+y6R1j^1s(Hso>MR6X)M*(IYk79D(D~W*?h&c9gFa5#_;GU zrZqo}KTt7kb5f&Xa!(dcV8!ef$$wI=n6f27Z9DUP{rdLge>{GKLO=KuIA@0`m)fm& zk@yaU*36yM%(g%}?=W+9>d8R$XsGl2sU=h?od+G}J_w?mqzFs=OF>%UfP4YzRnRRm-Fq;ZG_gI2YG@@}VCbuUl7 zv%`+=m)kro*HrQ9gzTS`+mc5BT5m}^6Im&CT$OeC&h&iFKqa|4YPc`&I&W&HIgm=1 zXr08k($d-con&QCaf0&ObNqei2X|{IQ}ffij!(4fC!ZoPv8?0J)I$VUPR}t?zv{*? zcbszw;)-;ia=4;BhZAncZP)Kq`;AIUdwkl@dONG1Wkk1rSY55*xTL0RA=CAmot?>@ z$17&-EakNFSXVEUo3tLTAjK$AZp3IrUAJePYZzv0=A2M8pmx3N)@dD`Kuu+R8=R50 zDzyaIl_^ZnuQc>y`AMS1*I#*iIV%jWP3rX$<;KvT8le4N$hFZnovT1f-?Gnw)LNSI zT6dmiz4?R!)>3T^9lu!SF&X*#^U;iBe&dCX;#ipY`bY7Ck@pBjj$Kq@y0`lVC{N~q zZ-AkUB_a08(Cr-dQkCk@XWKPpCgo8D*)g_N#Q1tQ?Jry}_8K+318i%UxEz;aCl%#B z91Y^Wm*Nw4T6JF_;&w}X1E8H+nwqlg^07-G!GdQ1&mjC|&8N(IeA0fh#PUsW?^p+< zIn+*F7fkEEa`pE~oVQ4+uyiVmE=}LQ=savo$<~2Pt1OnT#>e~K4hgI6+cI|p+QI*EdKrJva z*af4mEUm5m5GWdoJ7rS5ja(lua=(MG@>@!L2`;|cSru88lWL52=<;Bp-|m^G96zuu zCdRZxbY-^h9pGe5nWpnprZf&ju!M!w>%`VqhX%S|I(EH3;Z0CWLzNzq2k@M`UL{Gd zB=Ht=URFq1K)t!_?@T~l56JL9XZ1J(t8y$t9RX(vQ+7ABlWm*UK+iiCZvS*0pO#9S zLnYeyw)P5bd)H`+@kmKr9CHn{?^+#t6LwhpFW;a7e0*z&ZxGH=hE%&GK`GWJj)qiQ zozkS+V#|9EVUS}C^*nnv1bptviSxc8hl;eW&bbnm^zsH}iVlKs_EsuZiIhk&?{K`e z!AiLa;Twe4HoXNas`=ff=^Qc*!6n*3yk+7LXY&m*Q!VV?`ptM$eKM(rWSI&zM1nG& zpil;HpObj<>CU+zOJVGS<$%*yq6aK5dLMKF*E7~Wm5s+fkA9X%13o!Pv5rqXPZ9dv z53Htpn*F-AqucXy#99ZRb@*$!NaPp#?c(>Frq$N&WQbs6k;`nSR3}5 zp7VSxkbTw$sD^JC*l$1S?r#bB4E3~9K%nWv8KU~6kLPnO zx%rMU--)UO93lQ*rq6vTN%=o8?eGGRn5UTA%sgMH`s)fxPUEk91dIYqZ0qrLW%S2( zH7keoblN2F2_L(s_=zfH=wPz z&1s`R3ly`K>b`w^%6TG+Hul@*>UA966!;?16r~~UN*;^C-43iDiP|#Eq(H>*Sr23r zjY!@p&t9MXTrY8aMVN01S3BfS`cmu-*D8N{r|arEFb3KO%b(9hv<8Mb%6A{L3zL&{Wfh^NytJm@W0jS($EHZ;c)-&Gf}BqnuBDV=OAV zkGlGrh}gH}6_fDC^5k(2qOaEm9ja!8mdTN)$#IYx64UinusFYt@2No<)BK5)v=(f_AgJS8FhR;lZn2@4x2Fw&_OG5jFAs$mUMhdOj zUW-(ypn2)JmuUETX--5t>r$;4xijBlwC%k3KRM_Kf=*Dfjv#p`sJO(2mk*CQZwI4&3q>{^PSYpcTzLoNzHsGHS?X+%y&{V-$~7UCpGh( z)XaBMGv7(gd?z*Yoz&`#lKD<*<~ymG@1$nFlbZQXYUVqsneU`#zLWa5amaipHS?X+ z%y&{V-$~8Nd?z*Yoz%>CQZwI4b?uaTXTFn~`A%x)JE@uPq-MU8n)yy@<~ymG@1$nF zlbZQXs{2uf%y&{V-$~7UCpGh()XaBMYw)b}?AhFb%y&{V-$`|6$$TgEV2PRUq-MU8 zn)yy@<~ymG@1$nFlbZQX>Y=L5d?z*Yoz%>CQZwI4&3q>{^PSYpcTzLoNzHsG)yRA& zHS?X+%y&{V-$~7UCpGh()XaBMGv7(gd?z*Yoz%>CQZwI4&3q>{^PSYpcTzLoNzHsG sHS?X+%y&{V-$~7UCpGh(R3r19)XaBMGv7(gd?z*Yoz(wdd?)q)0ZTOHWB>pF diff --git a/rhodecode/i18n/en/LC_MESSAGES/rhodecode.po b/kallithea/i18n/en/LC_MESSAGES/kallithea.po rename from rhodecode/i18n/en/LC_MESSAGES/rhodecode.po rename to kallithea/i18n/en/LC_MESSAGES/kallithea.po --- a/rhodecode/i18n/en/LC_MESSAGES/rhodecode.po +++ b/kallithea/i18n/en/LC_MESSAGES/kallithea.po @@ -1,13 +1,13 @@ -# English translations for rhodecode. +# English translations for Kallithea. # Copyright (C) 2010 ORGANIZATION -# This file is distributed under the same license as the rhodecode project. +# This file is distributed under the same license as the Kallithea project. # FIRST AUTHOR , 2010. # msgid "" msgstr "" -"Project-Id-Version: rhodecode 0.1\n" +"Project-Id-Version: Kallithea 0.1\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2013-06-01 18:38+0200\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" "PO-Revision-Date: 2011-02-25 19:13+0100\n" "Last-Translator: FULL NAME \n" "Language-Team: en \n" @@ -17,1007 +17,1111 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -#: rhodecode/controllers/changelog.py:149 +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 +msgid "There are no changesets yet" +msgstr "" + +#: kallithea/controllers/changelog.py:186 msgid "All Branches" msgstr "" -#: rhodecode/controllers/changeset.py:84 +#: kallithea/controllers/changelog.py:189 +msgid "(closed)" +msgstr "" + +#: kallithea/controllers/changeset.py:87 msgid "Show white space" msgstr "" -#: rhodecode/controllers/changeset.py:91 rhodecode/controllers/changeset.py:98 +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 msgid "Ignore white space" msgstr "" -#: rhodecode/controllers/changeset.py:164 +#: kallithea/controllers/changeset.py:167 #, python-format -msgid "%s line context" -msgstr "" - -#: rhodecode/controllers/changeset.py:345 -#: rhodecode/controllers/pullrequests.py:481 +msgid "increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 #, python-format msgid "Status change -> %s" msgstr "" -#: rhodecode/controllers/changeset.py:376 +#: kallithea/controllers/changeset.py:386 msgid "" "Changing status on a changeset associated with a closed pull request is " "not allowed" msgstr "" -#: rhodecode/controllers/compare.py:74 -#: rhodecode/controllers/pullrequests.py:259 -msgid "There are no changesets yet" -msgstr "" - -#: rhodecode/controllers/error.py:69 +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +#, fuzzy +msgid "Select changeset" +msgstr "" + +#: kallithea/controllers/error.py:72 msgid "Home page" msgstr "" -#: rhodecode/controllers/error.py:98 +#: kallithea/controllers/error.py:101 msgid "The request could not be understood by the server due to malformed syntax." msgstr "" -#: rhodecode/controllers/error.py:101 +#: kallithea/controllers/error.py:104 msgid "Unauthorized access to resource" msgstr "" -#: rhodecode/controllers/error.py:103 +#: kallithea/controllers/error.py:106 msgid "You don't have permission to view this page" msgstr "" -#: rhodecode/controllers/error.py:105 +#: kallithea/controllers/error.py:108 msgid "The resource could not be found" msgstr "" -#: rhodecode/controllers/error.py:107 +#: kallithea/controllers/error.py:110 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." msgstr "" -#: rhodecode/controllers/feed.py:52 +#: kallithea/controllers/feed.py:55 #, python-format msgid "Changes on %s repository" msgstr "" -#: rhodecode/controllers/feed.py:53 +#: kallithea/controllers/feed.py:56 #, python-format msgid "%s %s feed" msgstr "" -#: rhodecode/controllers/feed.py:86 -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Changeset was too big and was cut off..." msgstr "" -#: rhodecode/controllers/feed.py:90 +#: kallithea/controllers/feed.py:93 #, python-format msgid "%s committed on %s" msgstr "" -#: rhodecode/controllers/files.py:89 +#: kallithea/controllers/files.py:92 msgid "Click here to add new file" msgstr "" -#: rhodecode/controllers/files.py:90 +#: kallithea/controllers/files.py:93 #, python-format -msgid "There are no files yet %s" -msgstr "" - -#: rhodecode/controllers/files.py:271 rhodecode/controllers/files.py:339 +msgid "There are no files yet. %s" +msgstr "" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 #, python-format msgid "This repository is has been locked by %s on %s" msgstr "" -#: rhodecode/controllers/files.py:283 -msgid "You can only edit files with revision being a valid branch " -msgstr "" - -#: rhodecode/controllers/files.py:297 +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:346 #, python-format -msgid "Edited file %s via RhodeCode" -msgstr "" - -#: rhodecode/controllers/files.py:313 +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "" + +#: kallithea/controllers/files.py:373 +msgid "You can only edit files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:403 msgid "No changes" msgstr "" -#: rhodecode/controllers/files.py:322 rhodecode/controllers/files.py:394 +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 #, python-format msgid "Successfully committed to %s" msgstr "" -#: rhodecode/controllers/files.py:327 rhodecode/controllers/files.py:405 -msgid "Error occurred during commit" -msgstr "" - -#: rhodecode/controllers/files.py:351 -msgid "Added file via RhodeCode" -msgstr "" - -#: rhodecode/controllers/files.py:368 +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:461 msgid "No content" msgstr "" -#: rhodecode/controllers/files.py:372 +#: kallithea/controllers/files.py:465 msgid "No filename" msgstr "" -#: rhodecode/controllers/files.py:397 +#: kallithea/controllers/files.py:490 msgid "Location must be relative path and must not contain .. in path" msgstr "" -#: rhodecode/controllers/files.py:431 +#: kallithea/controllers/files.py:524 msgid "Downloads disabled" msgstr "" -#: rhodecode/controllers/files.py:442 +#: kallithea/controllers/files.py:535 #, python-format msgid "Unknown revision %s" msgstr "" -#: rhodecode/controllers/files.py:444 +#: kallithea/controllers/files.py:537 msgid "Empty repository" msgstr "" -#: rhodecode/controllers/files.py:446 +#: kallithea/controllers/files.py:539 msgid "Unknown archive type" msgstr "" -#: rhodecode/controllers/files.py:631 -#: rhodecode/templates/changeset/changeset_range.html:9 -#: rhodecode/templates/email_templates/pull_request.html:12 -#: rhodecode/templates/pullrequests/pullrequest.html:124 +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 msgid "Changesets" msgstr "" -#: rhodecode/controllers/files.py:632 rhodecode/controllers/pullrequests.py:152 -#: rhodecode/controllers/summary.py:76 rhodecode/model/scm.py:682 -#: rhodecode/templates/switch_to_list.html:3 -#: rhodecode/templates/branches/branches.html:10 +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 msgid "Branches" msgstr "" -#: rhodecode/controllers/files.py:633 rhodecode/controllers/pullrequests.py:153 -#: rhodecode/controllers/summary.py:77 rhodecode/model/scm.py:693 -#: rhodecode/templates/switch_to_list.html:15 -#: rhodecode/templates/tags/tags.html:10 +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 msgid "Tags" msgstr "" -#: rhodecode/controllers/forks.py:176 -#, python-format -msgid "Forked repository %s as %s" -msgstr "" - -#: rhodecode/controllers/forks.py:190 +#: kallithea/controllers/forks.py:191 #, python-format msgid "An error occurred during repository forking %s" msgstr "" -#: rhodecode/controllers/journal.py:110 rhodecode/controllers/journal.py:153 +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 msgid "public journal" msgstr "" -#: rhodecode/controllers/journal.py:114 rhodecode/controllers/journal.py:157 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 msgid "journal" msgstr "" -#: rhodecode/controllers/login.py:138 -msgid "You have successfully registered into RhodeCode" -msgstr "" - -#: rhodecode/controllers/login.py:159 +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" +msgstr "" + +#: kallithea/controllers/login.py:237 msgid "Your password reset link was sent" msgstr "" -#: rhodecode/controllers/login.py:179 +#: kallithea/controllers/login.py:257 msgid "" "Your password reset was successful, new password has been sent to your " "email" msgstr "" -#: rhodecode/controllers/pullrequests.py:139 -#: rhodecode/templates/changeset/changeset.html:10 -#: rhodecode/templates/email_templates/changeset_comment.html:8 +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 msgid "Changeset" msgstr "" -#: rhodecode/controllers/pullrequests.py:149 +#: kallithea/controllers/pullrequests.py:157 msgid "Special" msgstr "" -#: rhodecode/controllers/pullrequests.py:150 +#: kallithea/controllers/pullrequests.py:158 msgid "Peer branches" msgstr "" -#: rhodecode/controllers/pullrequests.py:151 rhodecode/model/scm.py:688 -#: rhodecode/templates/switch_to_list.html:28 -#: rhodecode/templates/bookmarks/bookmarks.html:10 +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 msgid "Bookmarks" msgstr "" -#: rhodecode/controllers/pullrequests.py:324 +#: kallithea/controllers/pullrequests.py:330 msgid "Pull request requires a title with min. 3 chars" msgstr "" -#: rhodecode/controllers/pullrequests.py:326 -msgid "Error creating pull request" -msgstr "" - -#: rhodecode/controllers/pullrequests.py:346 +#: kallithea/controllers/pullrequests.py:332 +#, python-format +msgid "Error creating pull request: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:354 msgid "Successfully opened new pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:349 +#: kallithea/controllers/pullrequests.py:357 msgid "Error occurred during sending pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:388 +#: kallithea/controllers/pullrequests.py:397 msgid "Successfully deleted pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:484 +#: kallithea/controllers/pullrequests.py:485 msgid "Closing with" msgstr "" -#: rhodecode/controllers/pullrequests.py:521 +#: kallithea/controllers/pullrequests.py:522 msgid "Closing pull request on other statuses than rejected or approved forbidden" msgstr "" -#: rhodecode/controllers/search.py:132 +#: kallithea/controllers/search.py:135 msgid "Invalid search query. Try quoting it." msgstr "" -#: rhodecode/controllers/search.py:137 +#: kallithea/controllers/search.py:140 msgid "There is no index to search in. Please run whoosh indexer" msgstr "" -#: rhodecode/controllers/search.py:141 +#: kallithea/controllers/search.py:144 msgid "An error occurred during this search operation" msgstr "" -#: rhodecode/controllers/summary.py:182 +#: kallithea/controllers/summary.py:203 msgid "No data loaded yet" msgstr "" -#: rhodecode/controllers/summary.py:188 -#: rhodecode/templates/summary/summary.html:149 +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 msgid "Statistics are disabled for this repository" msgstr "" -#: rhodecode/controllers/admin/defaults.py:96 +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:97 msgid "Default settings updated successfully" msgstr "" -#: rhodecode/controllers/admin/defaults.py:110 +#: kallithea/controllers/admin/defaults.py:111 msgid "Error occurred during update of defaults" msgstr "" -#: rhodecode/controllers/admin/gists.py:56 +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 msgid "forever" msgstr "" -#: rhodecode/controllers/admin/gists.py:57 +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 #, fuzzy msgid "5 minutes" msgstr "" -#: rhodecode/controllers/admin/gists.py:58 +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 #, fuzzy msgid "1 hour" msgstr "" -#: rhodecode/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 #, fuzzy msgid "1 day" msgstr "" -#: rhodecode/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 #, fuzzy msgid "1 month" msgstr "" -#: rhodecode/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 msgid "Lifetime" msgstr "" -#: rhodecode/controllers/admin/gists.py:127 +#: kallithea/controllers/admin/gists.py:147 msgid "Error occurred during gist creation" msgstr "" -#: rhodecode/controllers/admin/gists.py:165 +#: kallithea/controllers/admin/gists.py:185 #, python-format msgid "Deleted gist %s" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:50 -msgid "BASE" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:51 -msgid "ONELEVEL" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:52 -msgid "SUBTREE" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:56 -msgid "NEVER" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:57 -msgid "ALLOW" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:58 -msgid "TRY" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:59 -msgid "DEMAND" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:60 -msgid "HARD" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:64 -msgid "No encryption" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:65 -msgid "LDAPS connection" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:66 -msgid "START_TLS on LDAP connection" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:124 -msgid "LDAP settings updated successfully" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:128 -msgid "Unable to activate ldap. The \"python-ldap\" library is missing." -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:145 -msgid "Error occurred during update of ldap settings" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:58 -#: rhodecode/controllers/admin/permissions.py:62 -#: rhodecode/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 msgid "None" msgstr "" -#: rhodecode/controllers/admin/permissions.py:59 -#: rhodecode/controllers/admin/permissions.py:63 -#: rhodecode/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 msgid "Read" msgstr "" -#: rhodecode/controllers/admin/permissions.py:60 -#: rhodecode/controllers/admin/permissions.py:64 -#: rhodecode/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 msgid "Write" msgstr "" -#: rhodecode/controllers/admin/permissions.py:61 -#: rhodecode/controllers/admin/permissions.py:65 -#: rhodecode/controllers/admin/permissions.py:69 -#: rhodecode/templates/admin/defaults/defaults.html:9 -#: rhodecode/templates/admin/ldap/ldap.html:9 -#: rhodecode/templates/admin/permissions/permissions.html:9 -#: rhodecode/templates/admin/repos/repo_add.html:10 -#: rhodecode/templates/admin/repos/repo_add.html:14 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:13 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:9 -#: rhodecode/templates/admin/users/user_add.html:8 -#: rhodecode/templates/admin/users/user_edit.html:9 -#: rhodecode/templates/admin/users/user_edit.html:133 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/admin/users/users.html:85 -#: rhodecode/templates/admin/users_groups/users_group_add.html:8 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 -#: rhodecode/templates/admin/users_groups/users_groups.html:9 -#: rhodecode/templates/base/base.html:317 -#: rhodecode/templates/base/base.html:318 -#: rhodecode/templates/base/base.html:324 -#: rhodecode/templates/base/base.html:325 +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 msgid "Admin" msgstr "" -#: rhodecode/controllers/admin/permissions.py:72 -#: rhodecode/controllers/admin/permissions.py:83 -#: rhodecode/controllers/admin/permissions.py:86 -#: rhodecode/controllers/admin/permissions.py:89 -#: rhodecode/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 msgid "Disabled" msgstr "" -#: rhodecode/controllers/admin/permissions.py:74 +#: kallithea/controllers/admin/permissions.py:78 msgid "Allowed with manual account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:80 msgid "Allowed with automatic account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:79 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1439 rhodecode/model/db.py:1444 +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 msgid "Manual activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:80 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1440 rhodecode/model/db.py:1445 +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 msgid "Automatic activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:84 -#: rhodecode/controllers/admin/permissions.py:87 -#: rhodecode/controllers/admin/permissions.py:90 -#: rhodecode/controllers/admin/permissions.py:93 +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 msgid "Enabled" msgstr "" -#: rhodecode/controllers/admin/permissions.py:138 -msgid "Default permissions updated successfully" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:152 +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:139 msgid "Error occurred during update of permissions" msgstr "" -#: rhodecode/controllers/admin/repos.py:128 -msgid "--REMOVE FORK--" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:168 -#, python-format -msgid "Created repository %s from %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:174 -#, python-format -msgid "Created repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:197 -#, python-format -msgid "Error creating repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:270 -#, python-format -msgid "Repository %s updated successfully" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:288 -#, python-format -msgid "Error occurred during update of repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:315 -#, python-format -msgid "Detached %s forks" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:318 -#, python-format -msgid "Deleted %s forks" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:323 -#, python-format -msgid "Deleted repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:326 -#, python-format -msgid "Cannot delete %s it still contains attached forks" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:331 -#, python-format -msgid "An error occurred during deletion of %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:345 -msgid "Repository permissions updated" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:375 -#: rhodecode/controllers/admin/repos_groups.py:332 -#: rhodecode/controllers/admin/users_groups.py:312 -msgid "An error occurred during revoking of permission" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:392 -msgid "An error occurred during deletion of repository stats" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:409 -msgid "An error occurred during cache invalidation" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:429 -#: rhodecode/controllers/admin/repos.py:456 -msgid "An error occurred during unlocking" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:447 -msgid "Unlocked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:450 -msgid "Locked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:452 -#, python-format -msgid "Repository has been %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:476 -msgid "Updated repository visibility in public journal" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:480 -msgid "An error occurred during setting this repository in public journal" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:485 rhodecode/model/validators.py:302 -msgid "Token mismatch" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:498 -msgid "Pulled from remote location" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:501 -msgid "An error occurred during pull from remote location" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:517 -msgid "Nothing" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:519 -#, python-format -msgid "Marked repo %s as fork of %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:523 -msgid "An error occurred during this operation" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:562 -msgid "An error occurred during creation of field" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:576 -msgid "An error occurred during removal of field" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:147 +#: kallithea/controllers/admin/repo_groups.py:186 #, python-format msgid "Created repository group %s" msgstr "" -#: rhodecode/controllers/admin/repos_groups.py:159 +#: kallithea/controllers/admin/repo_groups.py:198 #, python-format msgid "Error occurred during creation of repository group %s" msgstr "" -#: rhodecode/controllers/admin/repos_groups.py:217 +#: kallithea/controllers/admin/repo_groups.py:256 #, python-format msgid "Updated repository group %s" msgstr "" -#: rhodecode/controllers/admin/repos_groups.py:232 +#: kallithea/controllers/admin/repo_groups.py:271 #, python-format msgid "Error occurred during update of repository group %s" msgstr "" -#: rhodecode/controllers/admin/repos_groups.py:250 +#: kallithea/controllers/admin/repo_groups.py:289 #, python-format msgid "This group contains %s repositores and cannot be deleted" msgstr "" -#: rhodecode/controllers/admin/repos_groups.py:257 +#: kallithea/controllers/admin/repo_groups.py:296 #, python-format msgid "This group contains %s subgroups and cannot be deleted" msgstr "" -#: rhodecode/controllers/admin/repos_groups.py:263 +#: kallithea/controllers/admin/repo_groups.py:302 #, python-format msgid "Removed repository group %s" msgstr "" -#: rhodecode/controllers/admin/repos_groups.py:268 +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:237 +#, python-format +msgid "Created repository %s from %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:249 +#, python-format +msgid "Created repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:289 +#, python-format +msgid "Repository %s updated successfully" +msgstr "" + +#: kallithea/controllers/admin/repos.py:307 +#, python-format +msgid "Error occurred during update of repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:334 +#, python-format +msgid "Detached %s forks" +msgstr "" + +#: kallithea/controllers/admin/repos.py:337 +#, python-format +msgid "Deleted %s forks" +msgstr "" + +#: kallithea/controllers/admin/repos.py:342 +#, python-format +msgid "Deleted repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:345 +#, python-format +msgid "Cannot delete %s it still contains attached forks" +msgstr "" + +#: kallithea/controllers/admin/repos.py:350 #, python-format -msgid "Error occurred during deletion of repos group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:279 -#: rhodecode/controllers/admin/repos_groups.py:314 -#: rhodecode/controllers/admin/users_groups.py:300 -msgid "Cannot revoke permission for yourself as admin" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:294 -msgid "Repository Group permissions updated" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:123 +msgid "An error occurred during deletion of %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:402 +msgid "Repository permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "" + +#: kallithea/controllers/admin/repos.py:522 +msgid "Updated repository visibility in public journal" +msgstr "" + +#: kallithea/controllers/admin/repos.py:526 +msgid "An error occurred during setting this repository in public journal" +msgstr "" + +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 +msgid "Token mismatch" +msgstr "" + +#: kallithea/controllers/admin/repos.py:546 +msgid "Nothing" +msgstr "" + +#: kallithea/controllers/admin/repos.py:548 +#, python-format +msgid "Marked repo %s as fork of %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:555 +msgid "An error occurred during this operation" +msgstr "" + +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 +msgid "An error occurred during unlocking" +msgstr "" + +#: kallithea/controllers/admin/repos.py:595 +msgid "Unlocked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:598 +msgid "Locked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:600 +#, python-format +msgid "Repository has been %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "" + +#: kallithea/controllers/admin/repos.py:637 +msgid "Pulled from remote location" +msgstr "" + +#: kallithea/controllers/admin/repos.py:640 +msgid "An error occurred during pull from remote location" +msgstr "" + +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "" + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:176 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:215 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" msgstr "" -#: rhodecode/controllers/admin/settings.py:132 -msgid "Whoosh reindex task scheduled" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:163 +#: kallithea/controllers/admin/settings.py:270 msgid "Updated application settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:167 -#: rhodecode/controllers/admin/settings.py:304 -msgid "Error occurred during updating application settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:219 +#: kallithea/controllers/admin/settings.py:327 msgid "Updated visualisation settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:224 +#: kallithea/controllers/admin/settings.py:332 msgid "Error occurred during updating visualisation settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:300 -msgid "Updated VCS settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:314 +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "" + +#: kallithea/controllers/admin/settings.py:400 msgid "Added new hook" msgstr "" -#: rhodecode/controllers/admin/settings.py:326 +#: kallithea/controllers/admin/settings.py:414 msgid "Updated hooks" msgstr "" -#: rhodecode/controllers/admin/settings.py:330 +#: kallithea/controllers/admin/settings.py:418 msgid "Error occurred during hook creation" msgstr "" -#: rhodecode/controllers/admin/settings.py:349 -msgid "Email task created" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:413 -msgid "You can't edit this user since it's crucial for entire application" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:455 -msgid "Your account was updated successfully" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:470 -#: rhodecode/controllers/admin/users.py:198 -#, python-format -msgid "Error occurred during update of user %s" -msgstr "" - -#: rhodecode/controllers/admin/users.py:130 -#, python-format -msgid "Created user %s" -msgstr "" - -#: rhodecode/controllers/admin/users.py:142 -#, python-format -msgid "Error occurred during creation of user %s" -msgstr "" - -#: rhodecode/controllers/admin/users.py:176 -msgid "User updated successfully" -msgstr "" - -#: rhodecode/controllers/admin/users.py:214 -msgid "Successfully deleted user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:219 -msgid "An error occurred during deletion of user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:234 -msgid "You can't edit this user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:293 -#: rhodecode/controllers/admin/users_groups.py:372 -msgid "Updated permissions" -msgstr "" - -#: rhodecode/controllers/admin/users.py:297 -#: rhodecode/controllers/admin/users_groups.py:376 -msgid "An error occurred during permissions saving" -msgstr "" - -#: rhodecode/controllers/admin/users.py:311 -#, python-format -msgid "Added email %s to user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:317 -msgid "An error occurred during email saving" -msgstr "" - -#: rhodecode/controllers/admin/users.py:327 -msgid "Removed email from user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:340 -#, python-format -msgid "Added ip %s to user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:346 -msgid "An error occurred during ip saving" -msgstr "" - -#: rhodecode/controllers/admin/users.py:358 -msgid "Removed ip from user" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:162 +#: kallithea/controllers/admin/settings.py:444 +msgid "Whoosh reindex task scheduled" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:150 #, python-format msgid "Created user group %s" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:173 +#: kallithea/controllers/admin/user_groups.py:161 #, python-format msgid "Error occurred during creation of user group %s" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:210 +#: kallithea/controllers/admin/user_groups.py:199 #, python-format msgid "Updated user group %s" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:232 +#: kallithea/controllers/admin/user_groups.py:221 #, python-format msgid "Error occurred during update of user group %s" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:250 +#: kallithea/controllers/admin/user_groups.py:239 msgid "Successfully deleted user group" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:255 +#: kallithea/controllers/admin/user_groups.py:244 msgid "An error occurred during deletion of user group" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:274 +#: kallithea/controllers/admin/user_groups.py:311 msgid "Target group cannot be the same" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:280 +#: kallithea/controllers/admin/user_groups.py:317 msgid "User Group permissions updated" msgstr "" -#: rhodecode/lib/auth.py:544 +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "" + +#: kallithea/controllers/admin/users.py:135 +#, python-format +msgid "Created user %s" +msgstr "" + +#: kallithea/controllers/admin/users.py:149 +#, python-format +msgid "Error occurred during creation of user %s" +msgstr "" + +#: kallithea/controllers/admin/users.py:188 +msgid "User updated successfully" +msgstr "" + +#: kallithea/controllers/admin/users.py:223 +msgid "Successfully deleted user" +msgstr "" + +#: kallithea/controllers/admin/users.py:228 +msgid "An error occurred during deletion of user" +msgstr "" + +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 +msgid "You can't edit this user" +msgstr "" + +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "" + +#: kallithea/controllers/admin/users.py:489 +msgid "An error occurred during ip saving" +msgstr "" + +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "" + +#: kallithea/lib/auth.py:748 #, python-format msgid "IP %s not allowed" msgstr "" -#: rhodecode/lib/auth.py:593 +#: kallithea/lib/auth.py:809 msgid "You need to be a registered user to perform this action" msgstr "" -#: rhodecode/lib/auth.py:634 +#: kallithea/lib/auth.py:846 msgid "You need to be a signed in to view this page" msgstr "" -#: rhodecode/lib/diffs.py:66 +#: kallithea/lib/diffs.py:66 msgid "Binary file" msgstr "" -#: rhodecode/lib/diffs.py:82 +#: kallithea/lib/diffs.py:82 msgid "Changeset was too big and was cut off, use diff menu to display this diff" msgstr "" -#: rhodecode/lib/diffs.py:92 +#: kallithea/lib/diffs.py:92 msgid "No changes detected" msgstr "" -#: rhodecode/lib/helpers.py:428 -#, python-format -msgid "%a, %d %b %Y %H:%M:%S" -msgstr "" - -#: rhodecode/lib/helpers.py:539 -msgid "True" -msgstr "" - -#: rhodecode/lib/helpers.py:542 -msgid "False" -msgstr "" - -#: rhodecode/lib/helpers.py:580 +#: kallithea/lib/helpers.py:598 #, python-format msgid "Deleted branch: %s" msgstr "" -#: rhodecode/lib/helpers.py:583 +#: kallithea/lib/helpers.py:601 #, python-format msgid "Created tag: %s" msgstr "" -#: rhodecode/lib/helpers.py:596 +#: kallithea/lib/helpers.py:614 msgid "Changeset not found" msgstr "" -#: rhodecode/lib/helpers.py:646 +#: kallithea/lib/helpers.py:664 #, python-format msgid "Show all combined changesets %s->%s" msgstr "" -#: rhodecode/lib/helpers.py:652 +#: kallithea/lib/helpers.py:670 msgid "compare view" msgstr "" -#: rhodecode/lib/helpers.py:672 +#: kallithea/lib/helpers.py:690 msgid "and" msgstr "" -#: rhodecode/lib/helpers.py:673 +#: kallithea/lib/helpers.py:691 #, python-format msgid "%s more" msgstr "" -#: rhodecode/lib/helpers.py:674 rhodecode/templates/changelog/changelog.html:53 +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 msgid "revisions" msgstr "" -#: rhodecode/lib/helpers.py:698 +#: kallithea/lib/helpers.py:716 #, python-format msgid "fork name %s" msgstr "" -#: rhodecode/lib/helpers.py:715 -#: rhodecode/templates/pullrequests/pullrequest_show.html:8 +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 #, python-format msgid "Pull request #%s" msgstr "" -#: rhodecode/lib/helpers.py:725 +#: kallithea/lib/helpers.py:743 msgid "[deleted] repository" msgstr "" -#: rhodecode/lib/helpers.py:727 rhodecode/lib/helpers.py:739 +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 msgid "[created] repository" msgstr "" -#: rhodecode/lib/helpers.py:729 +#: kallithea/lib/helpers.py:747 msgid "[created] repository as fork" msgstr "" -#: rhodecode/lib/helpers.py:731 rhodecode/lib/helpers.py:741 +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 msgid "[forked] repository" msgstr "" -#: rhodecode/lib/helpers.py:733 rhodecode/lib/helpers.py:743 +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 msgid "[updated] repository" msgstr "" -#: rhodecode/lib/helpers.py:735 +#: kallithea/lib/helpers.py:753 msgid "[downloaded] archive from repository" msgstr "" -#: rhodecode/lib/helpers.py:737 +#: kallithea/lib/helpers.py:755 msgid "[delete] repository" msgstr "" -#: rhodecode/lib/helpers.py:745 +#: kallithea/lib/helpers.py:763 msgid "[created] user" msgstr "" -#: rhodecode/lib/helpers.py:747 +#: kallithea/lib/helpers.py:765 msgid "[updated] user" msgstr "" -#: rhodecode/lib/helpers.py:749 +#: kallithea/lib/helpers.py:767 msgid "[created] user group" msgstr "" -#: rhodecode/lib/helpers.py:751 +#: kallithea/lib/helpers.py:769 msgid "[updated] user group" msgstr "" -#: rhodecode/lib/helpers.py:753 +#: kallithea/lib/helpers.py:771 msgid "[commented] on revision in repository" msgstr "" -#: rhodecode/lib/helpers.py:755 +#: kallithea/lib/helpers.py:773 msgid "[commented] on pull request for" msgstr "" -#: rhodecode/lib/helpers.py:757 +#: kallithea/lib/helpers.py:775 msgid "[closed] pull request for" msgstr "" -#: rhodecode/lib/helpers.py:759 +#: kallithea/lib/helpers.py:777 msgid "[pushed] into" msgstr "" -#: rhodecode/lib/helpers.py:761 -msgid "[committed via RhodeCode] into repository" -msgstr "" - -#: rhodecode/lib/helpers.py:763 +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "" + +#: kallithea/lib/helpers.py:781 msgid "[pulled from remote] into repository" msgstr "" -#: rhodecode/lib/helpers.py:765 +#: kallithea/lib/helpers.py:783 msgid "[pulled] from" msgstr "" -#: rhodecode/lib/helpers.py:767 +#: kallithea/lib/helpers.py:785 msgid "[started following] repository" msgstr "" -#: rhodecode/lib/helpers.py:769 +#: kallithea/lib/helpers.py:787 msgid "[stopped following] repository" msgstr "" -#: rhodecode/lib/helpers.py:1088 +#: kallithea/lib/helpers.py:1101 #, python-format msgid " and %s more" msgstr "" -#: rhodecode/lib/helpers.py:1092 +#: kallithea/lib/helpers.py:1105 msgid "No Files" msgstr "" -#: rhodecode/lib/helpers.py:1158 +#: kallithea/lib/helpers.py:1171 msgid "new file" msgstr "" -#: rhodecode/lib/helpers.py:1161 +#: kallithea/lib/helpers.py:1174 msgid "mod" msgstr "" -#: rhodecode/lib/helpers.py:1164 +#: kallithea/lib/helpers.py:1177 msgid "del" msgstr "" -#: rhodecode/lib/helpers.py:1167 +#: kallithea/lib/helpers.py:1180 msgid "rename" msgstr "" -#: rhodecode/lib/helpers.py:1172 +#: kallithea/lib/helpers.py:1185 msgid "chmod" msgstr "" -#: rhodecode/lib/helpers.py:1404 +#: kallithea/lib/helpers.py:1417 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1025,3642 +1129,4523 @@ msgid "" "repositories" msgstr "" -#: rhodecode/lib/unionrepo.py:193 -msgid "cannot create new union repository" -msgstr "" - -#: rhodecode/lib/utils2.py:410 +#: kallithea/lib/utils2.py:415 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:411 +#: kallithea/lib/utils2.py:416 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:412 +#: kallithea/lib/utils2.py:417 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:413 +#: kallithea/lib/utils2.py:418 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:414 +#: kallithea/lib/utils2.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:415 +#: kallithea/lib/utils2.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:431 +#: kallithea/lib/utils2.py:436 #, python-format msgid "in %s" msgstr "" -#: rhodecode/lib/utils2.py:433 +#: kallithea/lib/utils2.py:438 #, python-format msgid "%s ago" msgstr "" -#: rhodecode/lib/utils2.py:435 +#: kallithea/lib/utils2.py:440 #, python-format msgid "in %s and %s" msgstr "" -#: rhodecode/lib/utils2.py:438 +#: kallithea/lib/utils2.py:443 #, python-format msgid "%s and %s ago" msgstr "" -#: rhodecode/lib/utils2.py:441 +#: kallithea/lib/utils2.py:446 msgid "just now" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1163 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1303 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1388 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1408 rhodecode/model/db.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 msgid "Repository no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1164 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1184 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1304 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1389 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1409 rhodecode/model/db.py:1414 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 msgid "Repository read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1165 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1185 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1305 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1390 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1410 rhodecode/model/db.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 msgid "Repository write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1166 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1186 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1306 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1391 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1411 rhodecode/model/db.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 msgid "Repository admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1168 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 msgid "Repositories Group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1169 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1309 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 msgid "Repositories Group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1170 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1310 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 msgid "Repositories Group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1171 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1311 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 msgid "Repositories Group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1173 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1193 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1313 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1398 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1406 rhodecode/model/db.py:1411 -msgid "RhodeCode Administrator" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1174 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1194 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1314 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1399 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1429 rhodecode/model/db.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 msgid "Repository creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1175 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1195 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1315 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1400 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1430 rhodecode/model/db.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 msgid "Repository creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1176 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1196 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1316 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1401 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1432 rhodecode/model/db.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 msgid "Repository forking disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1177 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1197 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1317 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1402 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1433 rhodecode/model/db.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 msgid "Repository forking enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1178 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1318 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 msgid "Register disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1319 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1404 -msgid "Register new user with RhodeCode with manual activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1202 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1407 -msgid "Register new user with RhodeCode with auto activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1623 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1643 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1763 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1838 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1934 rhodecode/model/db.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 msgid "Not Reviewed" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1624 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1644 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1764 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1839 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1935 rhodecode/model/db.py:1940 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 msgid "Approved" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1625 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1645 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1765 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1840 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1936 rhodecode/model/db.py:1941 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 msgid "Rejected" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1626 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1646 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1766 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1841 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1937 rhodecode/model/db.py:1942 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 msgid "Under Review" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1252 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1270 rhodecode/model/db.py:1275 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 msgid "top level" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1393 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1413 rhodecode/model/db.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 msgid "Repository group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1394 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1414 rhodecode/model/db.py:1419 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 msgid "Repository group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1395 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1415 rhodecode/model/db.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 msgid "Repository group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1396 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1416 rhodecode/model/db.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 msgid "Repository group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1418 rhodecode/model/db.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 msgid "User group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1419 rhodecode/model/db.py:1424 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 msgid "User group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1420 rhodecode/model/db.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 msgid "User group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1421 rhodecode/model/db.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 msgid "User group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1423 rhodecode/model/db.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 msgid "Repository Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1424 rhodecode/model/db.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 msgid "Repository Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1426 rhodecode/model/db.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 msgid "User Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1427 rhodecode/model/db.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 msgid "User Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1435 rhodecode/model/db.py:1440 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 msgid "Registration disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1436 rhodecode/model/db.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 msgid "User Registration with manual account activation" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1437 rhodecode/model/db.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 msgid "User Registration with automatic account activation" msgstr "" -#: rhodecode/model/comment.py:75 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:77 #, python-format msgid "on line %s" msgstr "" -#: rhodecode/model/comment.py:220 +#: kallithea/model/comment.py:222 msgid "[Mention]" msgstr "" -#: rhodecode/model/forms.py:43 +#: kallithea/model/forms.py:57 msgid "Please enter a login" msgstr "" -#: rhodecode/model/forms.py:44 +#: kallithea/model/forms.py:58 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "" -#: rhodecode/model/forms.py:52 +#: kallithea/model/forms.py:66 msgid "Please enter a password" msgstr "" -#: rhodecode/model/forms.py:53 +#: kallithea/model/forms.py:67 #, python-format msgid "Enter %(min)i characters or more" msgstr "" -#: rhodecode/model/notification.py:228 +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:231 #, python-format msgid "%(user)s commented on changeset at %(when)s" msgstr "" -#: rhodecode/model/notification.py:229 +#: kallithea/model/notification.py:232 #, python-format msgid "%(user)s sent message at %(when)s" msgstr "" -#: rhodecode/model/notification.py:230 +#: kallithea/model/notification.py:233 #, python-format msgid "%(user)s mentioned you at %(when)s" msgstr "" -#: rhodecode/model/notification.py:231 +#: kallithea/model/notification.py:234 #, python-format -msgid "%(user)s registered in RhodeCode at %(when)s" -msgstr "" - -#: rhodecode/model/notification.py:232 +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:235 #, python-format msgid "%(user)s opened new pull request at %(when)s" msgstr "" -#: rhodecode/model/notification.py:233 +#: kallithea/model/notification.py:236 #, python-format msgid "%(user)s commented on pull request at %(when)s" msgstr "" -#: rhodecode/model/pull_request.py:98 +#: kallithea/model/pull_request.py:107 #, python-format msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" msgstr "" -#: rhodecode/model/scm.py:674 +#: kallithea/model/scm.py:810 msgid "latest tip" msgstr "" -#: rhodecode/model/user.py:232 +#: kallithea/model/user.py:198 msgid "New user registration" msgstr "" -#: rhodecode/model/user.py:257 rhodecode/model/user.py:281 +#: kallithea/model/user.py:222 kallithea/model/user.py:247 msgid "You can't Edit this user since it's crucial for entire application" msgstr "" -#: rhodecode/model/user.py:303 +#: kallithea/model/user.py:270 msgid "You can't remove this user since it's crucial for entire application" msgstr "" -#: rhodecode/model/user.py:309 +#: kallithea/model/user.py:276 #, python-format msgid "" "user \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories. %s" msgstr "" -#: rhodecode/model/user.py:334 +#: kallithea/model/user.py:304 msgid "Password reset link" msgstr "" -#: rhodecode/model/user.py:366 +#: kallithea/model/user.py:333 msgid "Your new password" msgstr "" -#: rhodecode/model/user.py:367 +#: kallithea/model/user.py:334 #, python-format -msgid "Your new RhodeCode password:%s" -msgstr "" - -#: rhodecode/model/validators.py:38 rhodecode/model/validators.py:39 +msgid "Your new Kallithea password:%s" +msgstr "" + +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 msgid "Value cannot be an empty list" msgstr "" -#: rhodecode/model/validators.py:85 +#: kallithea/model/validators.py:120 #, python-format msgid "Username \"%(username)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:87 +#: kallithea/model/validators.py:122 #, python-format msgid "Username \"%(username)s\" is forbidden" msgstr "" -#: rhodecode/model/validators.py:89 +#: kallithea/model/validators.py:124 msgid "" "Username may only contain alphanumeric characters underscores, periods or" " dashes and must begin with alphanumeric character or underscore" msgstr "" -#: rhodecode/model/validators.py:117 +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:158 #, python-format msgid "Username %(username)s is not valid" msgstr "" -#: rhodecode/model/validators.py:136 +#: kallithea/model/validators.py:177 msgid "Invalid user group name" msgstr "" -#: rhodecode/model/validators.py:137 +#: kallithea/model/validators.py:178 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:139 +#: kallithea/model/validators.py:180 msgid "" "user group name may only contain alphanumeric characters underscores, " "periods or dashes and must begin with alphanumeric character" msgstr "" -#: rhodecode/model/validators.py:177 +#: kallithea/model/validators.py:218 msgid "Cannot assign this group as parent" msgstr "" -#: rhodecode/model/validators.py:178 +#: kallithea/model/validators.py:219 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:180 +#: kallithea/model/validators.py:221 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:238 +#: kallithea/model/validators.py:279 msgid "Invalid characters (non-ascii) in password" msgstr "" -#: rhodecode/model/validators.py:253 +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 msgid "Passwords do not match" msgstr "" -#: rhodecode/model/validators.py:270 +#: kallithea/model/validators.py:327 msgid "invalid password" msgstr "" -#: rhodecode/model/validators.py:271 +#: kallithea/model/validators.py:328 msgid "invalid user name" msgstr "" -#: rhodecode/model/validators.py:272 +#: kallithea/model/validators.py:329 msgid "Your account is disabled" msgstr "" -#: rhodecode/model/validators.py:316 +#: kallithea/model/validators.py:373 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "" -#: rhodecode/model/validators.py:318 +#: kallithea/model/validators.py:375 #, python-format msgid "Repository named %(repo)s already exists" msgstr "" -#: rhodecode/model/validators.py:319 +#: kallithea/model/validators.py:376 #, python-format msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" msgstr "" -#: rhodecode/model/validators.py:321 +#: kallithea/model/validators.py:378 #, python-format msgid "Repository group with name \"%(repo)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:438 +#: kallithea/model/validators.py:493 msgid "invalid clone url" msgstr "" -#: rhodecode/model/validators.py:439 +#: kallithea/model/validators.py:494 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" msgstr "" -#: rhodecode/model/validators.py:464 +#: kallithea/model/validators.py:519 msgid "Fork have to be the same type as parent" msgstr "" -#: rhodecode/model/validators.py:479 +#: kallithea/model/validators.py:534 msgid "You don't have permissions to create repository in this group" msgstr "" -#: rhodecode/model/validators.py:481 +#: kallithea/model/validators.py:536 msgid "no permission to create repository in root location" msgstr "" -#: rhodecode/model/validators.py:518 +#: kallithea/model/validators.py:585 msgid "You don't have permissions to create a group in this location" msgstr "" -#: rhodecode/model/validators.py:559 +#: kallithea/model/validators.py:626 msgid "This username or user group name is not valid" msgstr "" -#: rhodecode/model/validators.py:652 +#: kallithea/model/validators.py:719 msgid "This is not a valid path" msgstr "" -#: rhodecode/model/validators.py:667 +#: kallithea/model/validators.py:734 msgid "This e-mail address is already taken" msgstr "" -#: rhodecode/model/validators.py:687 +#: kallithea/model/validators.py:754 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "" -#: rhodecode/model/validators.py:724 +#: kallithea/model/validators.py:791 msgid "" "The LDAP Login attribute of the CN must be specified - this is the name " "of the attribute that is equivalent to \"username\"" msgstr "" -#: rhodecode/model/validators.py:737 +#: kallithea/model/validators.py:804 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" msgstr "" -#: rhodecode/model/validators.py:769 +#: kallithea/model/validators.py:836 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "" -#: rhodecode/model/validators.py:770 +#: kallithea/model/validators.py:837 #, python-format msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" msgstr "" -#: rhodecode/model/validators.py:803 +#: kallithea/model/validators.py:870 msgid "Key name can only consist of letters, underscore, dash or numbers" msgstr "" -#: rhodecode/model/validators.py:817 +#: kallithea/model/validators.py:884 msgid "Filename cannot be inside a directory" msgstr "" -#: rhodecode/templates/index.html:5 +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" +msgstr "" + +#: kallithea/templates/index.html:5 msgid "Dashboard" msgstr "" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/repo_switcher_list.html:4 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/users/user_edit_my_account.html:31 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/bookmarks/bookmarks.html:9 -#: rhodecode/templates/branches/branches.html:9 -#: rhodecode/templates/journal/journal.html:9 -#: rhodecode/templates/journal/journal.html:46 -#: rhodecode/templates/journal/journal.html:47 -#: rhodecode/templates/tags/tags.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 msgid "quick filter..." msgstr "" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/admin/repos/repos.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 msgid "repositories" msgstr "" -#: rhodecode/templates/index_base.html:13 -#: rhodecode/templates/index_base.html:18 -#: rhodecode/templates/admin/repos/repo_add.html:5 -#: rhodecode/templates/admin/repos/repos.html:21 -msgid "Add repository" -msgstr "" - -#: rhodecode/templates/index_base.html:15 -#: rhodecode/templates/index_base.html:20 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:31 -msgid "Add group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 -msgid "Edit group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" +msgstr "" + +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:32 msgid "You have admin right to this group, and can edit it" msgstr "" -#: rhodecode/templates/index_base.html:40 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:33 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:38 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:43 -#: rhodecode/templates/admin/users_groups/users_group_add.html:32 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 -#: rhodecode/templates/admin/users_groups/users_groups.html:37 -msgid "Group name" -msgstr "" - -#: rhodecode/templates/index_base.html:41 -#: rhodecode/templates/index_base.html:123 -#: rhodecode/templates/admin/repos/repo_add_base.html:56 -#: rhodecode/templates/admin/repos/repo_edit.html:68 -#: rhodecode/templates/admin/repos/repos.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:42 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:47 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:44 -#: rhodecode/templates/email_templates/changeset_comment.html:9 -#: rhodecode/templates/email_templates/pull_request.html:9 -#: rhodecode/templates/forks/fork.html:56 -#: rhodecode/templates/pullrequests/pullrequest.html:43 -#: rhodecode/templates/pullrequests/pullrequest_show.html:81 -#: rhodecode/templates/summary/summary.html:106 +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" +msgstr "" + +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 msgid "Description" msgstr "" -#: rhodecode/templates/index_base.html:51 -#: rhodecode/templates/admin/permissions/permissions.html:55 -#: rhodecode/templates/admin/repos/repo_add_base.html:29 -#: rhodecode/templates/admin/repos/repo_edit.html:50 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:57 -#: rhodecode/templates/forks/fork.html:47 -msgid "Repository group" -msgstr "" - -#: rhodecode/templates/index_base.html:121 -#: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit.html:32 -#: rhodecode/templates/admin/repos/repos.html:71 -#: rhodecode/templates/admin/users/user_edit_my_account.html:172 -#: rhodecode/templates/base/perms_summary.html:37 -#: rhodecode/templates/bookmarks/bookmarks.html:48 -#: rhodecode/templates/bookmarks/bookmarks_data.html:6 -#: rhodecode/templates/branches/branches.html:47 -#: rhodecode/templates/branches/branches_data.html:6 -#: rhodecode/templates/files/files_browser.html:47 -#: rhodecode/templates/journal/journal.html:193 -#: rhodecode/templates/journal/journal.html:283 -#: rhodecode/templates/summary/summary.html:55 -#: rhodecode/templates/summary/summary.html:124 -#: rhodecode/templates/tags/tags.html:48 -#: rhodecode/templates/tags/tags_data.html:6 +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 msgid "Name" msgstr "" -#: rhodecode/templates/index_base.html:124 +#: kallithea/templates/index_base.html:129 msgid "Last Change" msgstr "" -#: rhodecode/templates/index_base.html:126 -#: rhodecode/templates/admin/repos/repos.html:74 -#: rhodecode/templates/admin/users/user_edit_my_account.html:174 -#: rhodecode/templates/journal/journal.html:195 -#: rhodecode/templates/journal/journal.html:285 +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 msgid "Tip" msgstr "" -#: rhodecode/templates/index_base.html:128 -#: rhodecode/templates/admin/repos/repo_edit.html:114 -#: rhodecode/templates/admin/repos/repos.html:76 +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 msgid "Owner" msgstr "" -#: rhodecode/templates/index_base.html:136 -#: rhodecode/templates/admin/repos/repos.html:84 -#: rhodecode/templates/admin/users/user_edit_my_account.html:183 -#: rhodecode/templates/admin/users/users.html:107 -#: rhodecode/templates/bookmarks/bookmarks.html:74 -#: rhodecode/templates/branches/branches.html:73 -#: rhodecode/templates/journal/journal.html:204 -#: rhodecode/templates/journal/journal.html:294 -#: rhodecode/templates/tags/tags.html:74 +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 msgid "Click to sort ascending" msgstr "" -#: rhodecode/templates/index_base.html:137 -#: rhodecode/templates/admin/repos/repos.html:85 -#: rhodecode/templates/admin/users/user_edit_my_account.html:184 -#: rhodecode/templates/admin/users/users.html:108 -#: rhodecode/templates/bookmarks/bookmarks.html:75 -#: rhodecode/templates/branches/branches.html:74 -#: rhodecode/templates/journal/journal.html:205 -#: rhodecode/templates/journal/journal.html:295 -#: rhodecode/templates/tags/tags.html:75 +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 msgid "Click to sort descending" msgstr "" -#: rhodecode/templates/index_base.html:138 +#: kallithea/templates/index_base.html:143 msgid "No repositories found." msgstr "" -#: rhodecode/templates/index_base.html:139 -#: rhodecode/templates/admin/repos/repos.html:87 -#: rhodecode/templates/admin/users/user_edit_my_account.html:186 -#: rhodecode/templates/admin/users/users.html:110 -#: rhodecode/templates/bookmarks/bookmarks.html:77 -#: rhodecode/templates/branches/branches.html:76 -#: rhodecode/templates/journal/journal.html:207 -#: rhodecode/templates/journal/journal.html:297 -#: rhodecode/templates/tags/tags.html:77 +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 msgid "Data error." msgstr "" -#: rhodecode/templates/index_base.html:140 -#: rhodecode/templates/admin/repos/repos.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account.html:58 -#: rhodecode/templates/admin/users/user_edit_my_account.html:187 -#: rhodecode/templates/admin/users/users.html:111 -#: rhodecode/templates/bookmarks/bookmarks.html:78 -#: rhodecode/templates/branches/branches.html:77 -#: rhodecode/templates/journal/journal.html:208 -#: rhodecode/templates/journal/journal.html:298 -#: rhodecode/templates/tags/tags.html:78 +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 msgid "Loading..." msgstr "" -#: rhodecode/templates/login.html:5 rhodecode/templates/base/base.html:239 +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 msgid "Log In" msgstr "" -#: rhodecode/templates/login.html:21 +#: kallithea/templates/login.html:30 #, python-format msgid "Log In to %s" msgstr "" -#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20 -#: rhodecode/templates/admin/admin_log.html:5 -#: rhodecode/templates/admin/users/user_add.html:32 -#: rhodecode/templates/admin/users/user_edit.html:57 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:31 -#: rhodecode/templates/admin/users/users.html:77 -#: rhodecode/templates/base/base.html:215 -#: rhodecode/templates/summary/summary.html:123 +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 msgid "Username" msgstr "" -#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29 -#: rhodecode/templates/admin/ldap/ldap.html:46 -#: rhodecode/templates/admin/users/user_add.html:41 -#: rhodecode/templates/base/base.html:224 +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 msgid "Password" msgstr "" -#: rhodecode/templates/login.html:50 +#: kallithea/templates/login.html:62 msgid "Remember me" msgstr "" -#: rhodecode/templates/login.html:54 +#: kallithea/templates/login.html:66 msgid "Sign In" msgstr "" -#: rhodecode/templates/login.html:60 +#: kallithea/templates/login.html:72 msgid "Forgot your password ?" msgstr "" -#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:235 +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 msgid "Don't have an account ?" msgstr "" -#: rhodecode/templates/password_reset.html:5 +#: kallithea/templates/password_reset.html:5 msgid "Password Reset" msgstr "" -#: rhodecode/templates/password_reset.html:11 -msgid "Reset your password to" -msgstr "" - -#: rhodecode/templates/password_reset.html:21 -msgid "Email address" -msgstr "" - -#: rhodecode/templates/password_reset.html:30 -msgid "Reset my password" -msgstr "" - -#: rhodecode/templates/password_reset.html:31 +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" +msgstr "" + +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "" + +#: kallithea/templates/password_reset.html:64 msgid "Password reset link will be send to matching email address" msgstr "" -#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74 +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 msgid "Sign Up" msgstr "" -#: rhodecode/templates/register.html:11 -msgid "Sign Up to" -msgstr "" - -#: rhodecode/templates/register.html:38 +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:58 msgid "Re-enter password" msgstr "" -#: rhodecode/templates/register.html:47 -#: rhodecode/templates/admin/users/user_add.html:59 -#: rhodecode/templates/admin/users/user_edit.html:97 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:62 +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 msgid "First Name" msgstr "" -#: rhodecode/templates/register.html:56 -#: rhodecode/templates/admin/users/user_add.html:68 -#: rhodecode/templates/admin/users/user_edit.html:106 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:71 +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 msgid "Last Name" msgstr "" -#: rhodecode/templates/register.html:65 -#: rhodecode/templates/admin/users/user_add.html:77 -#: rhodecode/templates/admin/users/user_edit.html:115 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:80 -#: rhodecode/templates/summary/summary.html:125 +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 msgid "Email" msgstr "" -#: rhodecode/templates/register.html:76 +#: kallithea/templates/register.html:108 msgid "Your account will be activated right after registration" msgstr "" -#: rhodecode/templates/register.html:78 +#: kallithea/templates/register.html:110 msgid "Your account must wait for activation by administrator" msgstr "" -#: rhodecode/templates/repo_switcher_list.html:10 -#: rhodecode/templates/admin/defaults/defaults.html:44 -#: rhodecode/templates/admin/repos/repo_add_base.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:78 -#: rhodecode/templates/data_table/_dt_elements.html:61 -#: rhodecode/templates/summary/summary.html:77 -msgid "Private repository" -msgstr "" - -#: rhodecode/templates/repo_switcher_list.html:12 -#: rhodecode/templates/data_table/_dt_elements.html:63 -#: rhodecode/templates/summary/summary.html:79 -msgid "Public repository" -msgstr "" - -#: rhodecode/templates/switch_to_list.html:10 -#: rhodecode/templates/branches/branches_data.html:57 +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 msgid "There are no branches yet" msgstr "" -#: rhodecode/templates/switch_to_list.html:22 -#: rhodecode/templates/tags/tags_data.html:38 +#: kallithea/templates/switch_to_list.html:16 +msgid "Closed Branches" +msgstr "" + +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 msgid "There are no tags yet" msgstr "" -#: rhodecode/templates/switch_to_list.html:35 -#: rhodecode/templates/bookmarks/bookmarks_data.html:37 +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 msgid "There are no bookmarks yet" msgstr "" -#: rhodecode/templates/admin/admin.html:5 -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/base/base.html:73 +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 msgid "Admin journal" msgstr "" -#: rhodecode/templates/admin/admin.html:10 +#: kallithea/templates/admin/admin.html:13 msgid "journal filter..." msgstr "" -#: rhodecode/templates/admin/admin.html:12 -#: rhodecode/templates/journal/journal.html:11 +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 msgid "filter" msgstr "" -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 #, python-format msgid "%s entry" msgid_plural "%s entries" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/admin/admin_log.html:6 -#: rhodecode/templates/admin/repos/repos.html:77 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46 -#: rhodecode/templates/admin/users/user_edit_my_account.html:176 -#: rhodecode/templates/admin/users/users.html:87 -#: rhodecode/templates/admin/users_groups/users_groups.html:40 -#: rhodecode/templates/journal/journal.html:197 -#: rhodecode/templates/journal/journal.html:287 +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 msgid "Action" msgstr "" -#: rhodecode/templates/admin/admin_log.html:7 -#: rhodecode/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" msgstr "" -#: rhodecode/templates/admin/admin_log.html:8 -#: rhodecode/templates/bookmarks/bookmarks.html:49 -#: rhodecode/templates/bookmarks/bookmarks_data.html:7 -#: rhodecode/templates/branches/branches.html:48 -#: rhodecode/templates/branches/branches_data.html:7 -#: rhodecode/templates/tags/tags.html:49 -#: rhodecode/templates/tags/tags_data.html:7 +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 msgid "Date" msgstr "" -#: rhodecode/templates/admin/admin_log.html:9 +#: kallithea/templates/admin/admin_log.html:9 msgid "From IP" msgstr "" -#: rhodecode/templates/admin/admin_log.html:63 +#: kallithea/templates/admin/admin_log.html:63 msgid "No actions yet" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:5 -#: rhodecode/templates/admin/defaults/defaults.html:25 +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "" +"Comma separated list of plugins. Order of plugins is also order in which " +"Kallithea will try to authenticate user" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 msgid "Repositories defaults" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:11 -#: rhodecode/templates/base/base.html:80 +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 msgid "Defaults" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:35 -#: rhodecode/templates/admin/repos/repo_add_base.html:38 +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 msgid "Type" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:48 -#: rhodecode/templates/admin/repos/repo_add_base.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:82 -#: rhodecode/templates/forks/fork.html:69 +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 msgid "" "Private repositories are only visible to people explicitly added as " "collaborators." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:55 -#: rhodecode/templates/admin/repos/repo_edit.html:87 +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 msgid "Enable statistics" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:59 -#: rhodecode/templates/admin/repos/repo_edit.html:91 +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:96 +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 msgid "Enable downloads" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:100 +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:75 -#: rhodecode/templates/admin/repos/repo_edit.html:105 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:64 +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 msgid "Enable locking" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:79 -#: rhodecode/templates/admin/repos/repo_edit.html:109 +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 msgid "Enable lock-by-pulling on repository." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:84 -#: rhodecode/templates/admin/ldap/ldap.html:89 -#: rhodecode/templates/admin/permissions/permissions.html:122 -#: rhodecode/templates/admin/repos/repo_edit.html:141 -#: rhodecode/templates/admin/repos/repo_edit.html:166 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:72 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:96 -#: rhodecode/templates/admin/settings/hooks.html:73 -#: rhodecode/templates/admin/users/user_add.html:94 -#: rhodecode/templates/admin/users/user_edit.html:140 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:88 -#: rhodecode/templates/admin/users_groups/users_group_add.html:49 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:143 -#: rhodecode/templates/base/default_perms_box.html:53 -msgid "Save" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:5 -#: rhodecode/templates/base/base.html:299 -msgid "Gists" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "" +"Gist was update since you started editing. Copy your changes and click " +"%(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 #, python-format msgid "Private Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:12 +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 #, python-format msgid "Public Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:14 +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 msgid "Public Gists" msgstr "" -#: rhodecode/templates/admin/gists/index.html:31 -#: rhodecode/templates/admin/gists/show.html:24 -#: rhodecode/templates/base/base.html:302 -msgid "Create new gist" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:48 +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 msgid "Created" msgstr "" -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/index.html:53 -#: rhodecode/templates/admin/gists/show.html:43 -#: rhodecode/templates/admin/gists/show.html:45 -msgid "Expires" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/show.html:43 -msgid "never" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:68 +#: kallithea/templates/admin/gists/index.html:77 msgid "There are no gists yet" msgstr "" -#: rhodecode/templates/admin/gists/new.html:5 -#: rhodecode/templates/admin/gists/new.html:16 -msgid "New gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:37 -msgid "Gist description ..." -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:52 -msgid "Create private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:53 -msgid "Create public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:54 -#: rhodecode/templates/admin/permissions/permissions.html:123 -#: rhodecode/templates/admin/permissions/permissions.html:185 -#: rhodecode/templates/admin/repos/repo_edit.html:142 -#: rhodecode/templates/admin/repos/repo_edit.html:167 -#: rhodecode/templates/admin/repos/repo_edit.html:381 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:97 -#: rhodecode/templates/admin/settings/settings.html:115 -#: rhodecode/templates/admin/settings/settings.html:196 -#: rhodecode/templates/admin/settings/settings.html:288 -#: rhodecode/templates/admin/users/user_edit.html:141 -#: rhodecode/templates/admin/users/user_edit.html:198 -#: rhodecode/templates/admin/users/user_edit.html:246 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:89 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:144 -#: rhodecode/templates/base/default_perms_box.html:54 -#: rhodecode/templates/files/files_add.html:80 -#: rhodecode/templates/files/files_edit.html:66 -#: rhodecode/templates/pullrequests/pullrequest.html:86 +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 msgid "Reset" msgstr "" -#: rhodecode/templates/admin/gists/show.html:5 -msgid "gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:9 +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 msgid "Gist" msgstr "" -#: rhodecode/templates/admin/gists/show.html:36 -msgid "Public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:38 -msgid "Private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:54 -#: rhodecode/templates/admin/repos/repo_edit.html:299 -#: rhodecode/templates/changeset/changeset_file_comment.html:40 +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 msgid "Delete" msgstr "" -#: rhodecode/templates/admin/gists/show.html:54 +#: kallithea/templates/admin/gists/show.html:59 #, fuzzy -msgid "Confirm to delete this gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:63 -#: rhodecode/templates/admin/gists/show.html:84 -#: rhodecode/templates/files/files_edit.html:48 -#: rhodecode/templates/files/files_source.html:25 -#: rhodecode/templates/files/files_source.html:55 -msgid "Show as raw" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:71 +msgid "Confirm to delete this Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:76 msgid "created" msgstr "" -#: rhodecode/templates/admin/ldap/ldap.html:5 -msgid "LDAP administration" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:11 -#: rhodecode/templates/admin/users/users.html:86 -#: rhodecode/templates/base/base.html:79 -msgid "LDAP" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:28 -msgid "Connection settings" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:30 -msgid "Enable LDAP" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:34 -msgid "Host" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:38 -msgid "Port" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:42 -msgid "Account" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:50 -msgid "Connection security" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:54 -msgid "Certificate Checks" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:57 -msgid "Search settings" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:59 -msgid "Base DN" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:63 -msgid "LDAP Filter" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:67 -msgid "LDAP Search Scope" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:70 -msgid "Attribute mappings" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:72 -msgid "Login Attribute" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:76 -msgid "First Name Attribute" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:80 -msgid "Last Name Attribute" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:84 -msgid "E-mail Attribute" -msgstr "" - -#: rhodecode/templates/admin/notifications/notifications.html:5 -#: rhodecode/templates/admin/notifications/notifications.html:9 +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "" +"Your user is in an external Source of Record; some details cannot be " +"managed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 msgid "My Notifications" msgstr "" -#: rhodecode/templates/admin/notifications/notifications.html:29 +#: kallithea/templates/admin/notifications/notifications.html:32 msgid "All" msgstr "" -#: rhodecode/templates/admin/notifications/notifications.html:30 +#: kallithea/templates/admin/notifications/notifications.html:33 #, fuzzy msgid "Comments" msgstr "" -#: rhodecode/templates/admin/notifications/notifications.html:31 -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:8 -msgid "Pull requests" -msgstr "" - -#: rhodecode/templates/admin/notifications/notifications.html:35 +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:38 msgid "Mark all read" msgstr "" -#: rhodecode/templates/admin/notifications/notifications_data.html:39 +#: kallithea/templates/admin/notifications/notifications_data.html:40 msgid "No notifications here yet" msgstr "" -#: rhodecode/templates/admin/notifications/show_notification.html:5 -#: rhodecode/templates/admin/notifications/show_notification.html:11 +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 msgid "Show notification" msgstr "" -#: rhodecode/templates/admin/notifications/show_notification.html:9 -#: rhodecode/templates/base/base.html:253 +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 msgid "Notifications" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:5 msgid "Permissions administration" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:11 -#: rhodecode/templates/admin/repos/repo_edit.html:151 -#: rhodecode/templates/admin/repos/repo_edit.html:158 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:81 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:88 -#: rhodecode/templates/admin/users/user_edit.html:150 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:129 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:136 -#: rhodecode/templates/base/base.html:78 +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 msgid "Permissions" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:24 -msgid "Default permissions" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:31 +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 msgid "Anonymous access" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:49 +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without need to log in. Anonymous users use %s " +"user permissions" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 msgid "" "All default permissions on each repository will be reset to chosen " "permission, note that all custom default permission on repositories will " "be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:50 -#: rhodecode/templates/admin/permissions/permissions.html:63 -#: rhodecode/templates/admin/permissions/permissions.html:77 +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 msgid "Overwrite existing settings" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:62 +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 msgid "" "All default permissions on each repository group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 msgid "User group" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:76 +#: kallithea/templates/admin/permissions/permissions_globals.html:53 msgid "" "All default permissions on each user group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:83 +#: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:91 +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "" +"Write permission to repository groups allows creating repositories inside" +" that group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 msgid "User group creation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:99 +#: kallithea/templates/admin/permissions/permissions_globals.html:85 msgid "Repository forking" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:107 +#: kallithea/templates/admin/permissions/permissions_globals.html:93 msgid "Registration" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:115 +#: kallithea/templates/admin/permissions/permissions_globals.html:101 msgid "External auth account activation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:133 -msgid "Default User Permissions" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:144 -#: rhodecode/templates/admin/users/user_edit.html:207 -msgid "Allowed IP addresses" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:158 -#: rhodecode/templates/admin/repos/repo_edit.html:340 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#: rhodecode/templates/admin/users/user_edit.html:175 -#: rhodecode/templates/admin/users/user_edit.html:220 -#: rhodecode/templates/admin/users_groups/users_groups.html:54 -#: rhodecode/templates/data_table/_dt_elements.html:122 -#: rhodecode/templates/data_table/_dt_elements.html:136 -msgid "delete" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:159 -#: rhodecode/templates/admin/users/user_edit.html:221 +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 #, fuzzy, python-format msgid "Confirm to delete this ip: %s" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:165 -#: rhodecode/templates/admin/users/user_edit.html:227 +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 msgid "All IP addresses are allowed" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:176 -#: rhodecode/templates/admin/users/user_edit.html:238 +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:184 -#: rhodecode/templates/admin/repos/repo_add_base.html:73 -#: rhodecode/templates/admin/repos/repo_edit.html:380 -#: rhodecode/templates/admin/users/user_edit.html:197 -#: rhodecode/templates/admin/users/user_edit.html:245 -msgid "Add" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add.html:12 -#: rhodecode/templates/admin/repos/repo_add.html:16 -#: rhodecode/templates/base/base.html:74 rhodecode/templates/base/base.html:88 -#: rhodecode/templates/base/base.html:116 -#: rhodecode/templates/base/base.html:275 -msgid "Repositories" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add.html:19 -msgid "Add new" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:20 -#: rhodecode/templates/summary/summary.html:96 -#: rhodecode/templates/summary/summary.html:97 -msgid "Clone from" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:24 -#: rhodecode/templates/admin/repos/repo_edit.html:45 -msgid "Optional http[s] url from which repository should be cloned." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:33 -#: rhodecode/templates/forks/fork.html:51 -msgid "Optionaly select a group to put this repository into." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:42 -msgid "Type of repository to create." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:47 -#: rhodecode/templates/admin/repos/repo_edit.html:59 -#: rhodecode/templates/forks/fork.html:38 -msgid "Landing revision" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:51 -#: rhodecode/templates/admin/repos/repo_edit.html:63 -#: rhodecode/templates/forks/fork.html:42 -msgid "Default revision for files page, downloads, whoosh and readme" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:60 -#: rhodecode/templates/admin/repos/repo_edit.html:72 -#: rhodecode/templates/forks/fork.html:60 -msgid "Keep it short and to the point. Use a README file for longer descriptions." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:8 -msgid "Edit repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:12 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:11 -#: rhodecode/templates/base/base.html:81 rhodecode/templates/base/base.html:134 -#: rhodecode/templates/summary/summary.html:212 +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 msgid "Settings" msgstr "" -#: rhodecode/templates/admin/repos/repo_edit.html:36 -msgid "Non-changeable id" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:41 -msgid "Clone uri" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:54 -msgid "Optional select a group to put this repository into." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:119 -msgid "Change owner of this repository." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:177 -msgid "Advanced settings" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:180 -msgid "Statistics" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Reset current statistics" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Confirm to remove current statistics" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:187 -msgid "Fetched to rev" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:188 -msgid "Stats gathered" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:196 -msgid "Remote" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Pull changes from remote location" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Confirm to pull changes from remote side" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:211 -msgid "Cache" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Invalidate repository cache" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Confirm to invalidate repository cache" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:218 -msgid "" -"Manually invalidate cache for this repository. On first access repository" -" will be cached again" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:223 -msgid "List of cached values" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:226 -msgid "Prefix" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:227 -msgid "Key" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:228 -#: rhodecode/templates/admin/users/user_add.html:86 -#: rhodecode/templates/admin/users/user_edit.html:124 -#: rhodecode/templates/admin/users/users.html:84 -#: rhodecode/templates/admin/users_groups/users_group_add.html:41 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 -#: rhodecode/templates/admin/users_groups/users_groups.html:39 -msgid "Active" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:243 -#: rhodecode/templates/base/base.html:292 -#: rhodecode/templates/base/base.html:293 -msgid "Public journal" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:249 -msgid "Remove from public journal" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:251 -msgid "Add to public journal" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:256 -msgid "" -"All actions made on this repository will be accessible to everyone in " -"public journal" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:263 -msgid "Locking" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Unlock locked repo" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Confirm to unlock repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Lock repo" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Confirm to lock repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:272 -msgid "Repository is not locked" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:277 -msgid "Force locking on repository. Works only when anonymous access is disabled" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:284 -msgid "Set as fork of" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:289 -msgid "Set" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:293 -msgid "Manually set this repository as a fork of another from the list" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Remove this repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Confirm to delete this repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:310 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 #, python-format -msgid "this repository has %s fork" -msgid_plural "this repository has %s forks" -msgstr[0] "" -msgstr[1] "" - -#: rhodecode/templates/admin/repos/repo_edit.html:311 -msgid "Detach forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:312 -msgid "Delete forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:315 -msgid "" -"This repository will be renamed in a special way in order to be " -"unaccesible for RhodeCode and VCS systems. If you need to fully delete it" -" from file system please do it manually" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:329 -msgid "Extra fields" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:341 -#, fuzzy, python-format -msgid "Confirm to delete this field: %s" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:355 -msgid "New field key" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:363 -msgid "New field label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:366 -msgid "Enter short label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:372 -msgid "New field description" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:375 -msgid "Enter description of a field" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:3 -msgid "none" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:4 -msgid "read" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:5 -msgid "write" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:6 -msgid "admin" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:7 -msgid "member" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:16 -msgid "private repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:19 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:28 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:20 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:35 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:20 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:35 -msgid "default" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:33 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:58 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:25 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:55 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:25 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:55 -msgid "revoke" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:83 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:81 -msgid "Add another member" -msgstr "" - -#: rhodecode/templates/admin/repos/repos.html:5 -msgid "Repositories administration" -msgstr "" - -#: rhodecode/templates/admin/repos/repos.html:86 -#: rhodecode/templates/admin/users/user_edit_my_account.html:185 -#: rhodecode/templates/admin/users/users.html:109 -#: rhodecode/templates/bookmarks/bookmarks.html:76 -#: rhodecode/templates/branches/branches.html:75 -#: rhodecode/templates/journal/journal.html:206 -#: rhodecode/templates/journal/journal.html:296 -#: rhodecode/templates/tags/tags.html:76 -msgid "No records found." -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:87 -msgid "apply to children" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:88 -msgid "" -"Set or revoke permission to all children of that group, including non-" -"private repositories and other groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:4 -#, python-format -msgid "%s Group Dashboard" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:9 -msgid "Home" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:13 -msgid "with" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5 -msgid "Add repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:16 -#: rhodecode/templates/base/base.html:75 rhodecode/templates/base/base.html:91 -msgid "Repository groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:13 -msgid "Add new repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:51 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:56 -msgid "Group parent" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:59 -msgid "save" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5 -msgid "Edit repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:13 -#, python-format -msgid "Edit repository group %s" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:27 -msgid "Add child group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:68 -msgid "" -"Enable lock-by-pulling on group. This option will be applied to all other" -" groups and repositories inside" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5 -msgid "Repository groups administration" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:45 -msgid "Number of toplevel repositories" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:64 -#: rhodecode/templates/admin/users_groups/users_groups.html:48 -#: rhodecode/templates/changeset/changeset_file_comment.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:171 -msgid "Edit" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:65 -#: rhodecode/templates/admin/users_groups/users_groups.html:49 -#: rhodecode/templates/base/perms_summary.html:29 -#: rhodecode/templates/base/perms_summary.html:60 -#: rhodecode/templates/base/perms_summary.html:62 -#: rhodecode/templates/data_table/_dt_elements.html:116 -#: rhodecode/templates/data_table/_dt_elements.html:117 -#: rhodecode/templates/data_table/_dt_elements.html:130 -#: rhodecode/templates/data_table/_dt_elements.html:131 -msgid "edit" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 +msgid "Repository Group: %s" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 #, python-format msgid "Confirm to delete this group: %s with %s repository" msgid_plural "Confirm to delete this group: %s with %s repositories" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:78 -msgid "There are no repository groups yet" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:5 -#: rhodecode/templates/admin/settings/settings.html:5 -msgid "Settings administration" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:24 -msgid "Built in hooks - read only" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:40 -msgid "Custom hooks" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:56 -msgid "remove" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:88 -msgid "Failed to remove hook" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:26 -msgid "Remap and rescan repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:34 -msgid "Rescan option" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:40 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +#, fuzzy +msgid "Delete this repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "" +"Set or revoke permission to all children of that group, including non-" +"private repositories and other groups if selected." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 msgid "" -"In case a repository was deleted from filesystem and there are leftovers " -"in the database check this option to scan obsolete data in database and " -"remove it." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:41 -msgid "Destroy old data" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:43 +"Enable lock-by-pulling on group. This option will be applied to all other" +" groups and repositories inside" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, fuzzy, python-format +msgid "%s Repository group dashboard" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is beeing created, you will be redirected " +"when this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:42 msgid "" -"Rescan repositories location for new repositories. Also deletes obsolete " -"if `destroy` flag is checked " -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:48 -msgid "Rescan repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:54 -msgid "Whoosh indexing" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:62 -msgid "Index build option" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:67 -msgid "Build from scratch" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:73 -msgid "Reindex" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:79 -msgid "Global application settings" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:88 -msgid "Site branding" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:97 -msgid "HTTP authentication realm" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:106 -msgid "Google Analytics code" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:114 -#: rhodecode/templates/admin/settings/settings.html:195 -#: rhodecode/templates/admin/settings/settings.html:287 -msgid "Save settings" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:121 -msgid "Visualisation settings" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:129 -msgid "General" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:134 -msgid "Use repository extra fields" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:136 -msgid "Allows storing additional customized fields per repository." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:139 -msgid "Show RhodeCode version" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:141 -msgid "Shows or hides displayed version of RhodeCode in the footer" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:146 -msgid "Dashboard items" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:150 +"We're sorry but error occured during this operation. Please check your " +"Kallithea server logs, or contact administrator." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, fuzzy, python-format +msgid "%s repository settings" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +msgid "Remote" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Remove from public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +msgid "Add to public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 +msgid "" +"All actions made on this repository will be accessible to everyone in " +"public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 +msgid "Confirm to unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 +msgid "Confirm to lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 +msgid "Repository is not locked" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 msgid "" -"Number of items displayed in lightweight dashboard before pagination is " -"shown." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:155 -msgid "Icons" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:160 -msgid "Show public repo icon on repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:164 -msgid "Show private repo icon on repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:166 -msgid "Show public/private icons next to repositories names" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:172 -msgid "Meta-Tagging" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:177 -msgid "Stylify recognised metatags:" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:204 -msgid "VCS settings" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:213 -msgid "Web" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:218 -msgid "Require SSL for vcs operations" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:220 +"Force locking on repository. Works only when anonymous access is " +"disabled. Trigering a pull locks repository by user who pulled, only the " +"same user can unlock by doing a push" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +#, fuzzy +msgid "Delete this repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 +#, python-format +msgid "this repository has %s fork" +msgid_plural "this repository has %s forks" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 +msgid "Detach forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 +msgid "Delete forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "" +"This repository will be renamed in a special way in order to be " +"unaccesible for Kallithea and VCS systems. If you need to fully delete it" +" from file system please do it manually" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 msgid "" -"RhodeCode will require SSL for pushing or pulling. If SSL is missing it " -"will return HTTP Error 406: Not Acceptable" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:226 -msgid "Hooks" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:231 -msgid "Update repository after push (hg update)" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:235 -msgid "Show repository size after push" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:239 -msgid "Log user push commands" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:243 -msgid "Log user pull commands" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:247 -msgid "Advanced setup" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:252 -msgid "Mercurial Extensions" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:257 -msgid "Enable largefiles extension" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:261 -msgid "Enable hgsubversion extension" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:263 -msgid "" -"Requires hgsubversion library installed. Allows cloning from svn remote " -"locations" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:274 -msgid "Repositories location" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:279 -msgid "" -"Click to unlock. You must restart RhodeCode in order to make this setting" -" take effect." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:280 -#: rhodecode/templates/base/base.html:143 -msgid "Unlock" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:282 +"Manually invalidate cache for this repository. On first access repository" +" will be cached again" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#, fuzzy, python-format +msgid "Confirm to delete this field: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 +msgid "New field key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 +msgid "New field label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 +msgid "Enter short label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 +msgid "New field description" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +msgid "Enter description of a field" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 +msgid "private repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 msgid "" -"Location where repositories are stored. After changing this value a " -"restart, and rescan is required" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:303 -msgid "Test Email" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:311 -msgid "Email to" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:319 +"In case this repository is renamed or moved into another group the " +"repository url changes.\n" +" Using above url guarantees that this " +"repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases" +" that you need to hardcode the url into 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "" + +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 +msgid "Settings administration" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:16 +#, fuzzy +msgid "SMTP auth" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:39 msgid "Send" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:325 -msgid "System Info and Packages" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:328 -#: rhodecode/templates/changelog/changelog.html:51 -msgid "Show" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:5 -msgid "Add user" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:10 -#: rhodecode/templates/admin/users/user_edit.html:11 -#: rhodecode/templates/base/base.html:76 -msgid "Users" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:12 -#: rhodecode/templates/admin/users/users.html:23 -msgid "Add new user" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:50 -msgid "Password confirmation" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:5 -msgid "Edit user" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:13 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 -#, python-format -msgid "Edit %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:34 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:10 -msgid "Change your avatar at" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:35 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:11 -msgid "Using" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:43 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:20 -msgid "API key" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:50 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:25 -msgid "Current IP" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:70 -msgid "LDAP DN" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:79 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:44 -msgid "New password" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:53 -msgid "New password confirmation" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:163 -msgid "Email addresses" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:176 +#: kallithea/templates/admin/settings/settings_global.html:8 +msgid "Site branding" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:18 +msgid "HTTP authentication realm" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:27 +msgid "Google Analytics code" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:50 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 +msgid "Save settings" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "" +"Hooks can be used to trigger actions on certain events such as push / " +"pull. They can trigger Python functions or external applications." +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 +msgid "Custom hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:69 +msgid "Failed to remove hook" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:6 +msgid "Rescan option" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:11 +msgid "Destroy old data" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:13 +msgid "" +"In case a repository was deleted from filesystem and it still exists in " +"the database check this option to scan obsolete data in database and " +"remove it." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 +msgid "" +"Each cache data for repositories will be cleaned with this option " +"selected. Use this to reload data and clear cache keys." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 +msgid "" +"Verify if Kallitheas GIT hooks are installed for each repository. Current" +" hooks will be updated to latest version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:7 +msgid "Index build option" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:12 +msgid "Build from scratch" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:15 +msgid "" +"This option completely reindex all the files within Kallithea for proper " +"fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:21 +msgid "Reindex" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 +msgid "Web" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:11 +msgid "Require SSL for vcs operations" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:13 +msgid "" +"Activate to set Kallithea to require SSL for pushing or pulling. If SSL " +"certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 +msgid "Show repository size after push" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:28 +msgid "Log user push commands" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:32 +msgid "Log user pull commands" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:36 +msgid "Update repository after push (hg update)" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:42 +msgid "Mercurial Extensions" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:47 +msgid "Enable largefiles extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:51 +msgid "Enable hgsubversion extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:53 +msgid "" +"Requires hgsubversion library to be installed. Allows cloning remote SVN " +"repositories and migrates them to Mercurial type." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 +msgid "Repositories location" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting" +" take effect." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:72 +msgid "" +"Filesystem location where repositories should be stored. After changing " +"this value a restart and rescan of the repository folder are required." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:8 +msgid "General" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:13 +msgid "Use repository extra fields" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:15 +msgid "Allows storing additional customized fields per repository." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:30 +msgid "" +"Gravatar url allows you to use other avatar server application.\n" +" Following " +"variables of the URL will be replaced accordingly.\n" +" {scheme} " +"'http' or 'https' sent from running Kallithea server,\n" +" {email} user " +"email,\n" +" {md5email} md5 " +"hash of the user email (like at gravatar.com),\n" +" {size} size " +"of the image that is expected from the server application,\n" +" {netloc} " +"network location/server host of running Kallithea server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:42 +msgid "" +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}'," +" available vars:\n" +" {scheme} 'http' " +"or 'https' sent from running Kallithea server,\n" +" {user} current " +"user username,\n" +" {netloc} network " +"location/server host of running Kallithea server,\n" +" {repo} full " +"repository name,\n" +" {repoid} ID of " +"repository, can be used to contruct clone-by-id" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:54 +msgid "Dashboard items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:58 +msgid "" +"Number of items displayed in the main page dashboard before pagination is" +" shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:68 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:74 +msgid "Icons" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:79 +msgid "Show public repo icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:83 +msgid "Show private repo icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:91 +msgid "Meta-Tagging" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:110 +msgid "" +"Parses meta tags from repository description field and turns them into " +"colored tags." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 +msgid "Add user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 +msgid "User groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 #, python-format -msgid "Confirm to delete this email: %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:190 -msgid "New email address" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:5 -#: rhodecode/templates/base/base.html:254 -msgid "My account" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:9 -msgid "My Account" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:35 -msgid "My permissions" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:38 -#: rhodecode/templates/journal/journal.html:54 -msgid "My repos" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:41 -msgid "My pull requests" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:4 -msgid "Show closed pull requests" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:6 -msgid "Opened by me" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:17 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:45 -#: rhodecode/templates/pullrequests/pullrequest_data.html:11 -#: rhodecode/templates/pullrequests/pullrequest_show.html:27 -#: rhodecode/templates/pullrequests/pullrequest_show.html:42 -msgid "Closed" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:23 -msgid "Confirm to delete this pull request" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:30 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:51 -msgid "Nothing here yet" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:34 -msgid "I participate in" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:42 -#: rhodecode/templates/pullrequests/pullrequest_data.html:8 +msgid "%s user group settings" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 +msgid "Members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 #, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:5 -msgid "Users administration" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:9 -msgid "users" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:80 -msgid "Firstname" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:81 -msgid "Lastname" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:82 -msgid "Last login" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:5 -msgid "Add user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:10 -#: rhodecode/templates/admin/users_groups/users_groups.html:11 -#: rhodecode/templates/base/base.html:77 rhodecode/templates/base/base.html:94 -msgid "User groups" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:12 -#: rhodecode/templates/admin/users_groups/users_groups.html:26 -msgid "Add new user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 -msgid "Edit user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 -msgid "UserGroups" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 -#: rhodecode/templates/admin/users_groups/users_groups.html:38 -msgid "Members" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 -msgid "Chosen group members" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 -msgid "Remove all elements" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 -msgid "Available members" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 -msgid "Add all elements" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:109 -msgid "No members yet" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:117 -msgid "Global Permissions" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:5 -msgid "User groups administration" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:55 +msgid "User Group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 #, fuzzy, python-format msgid "Confirm to delete this user group: %s" msgstr "" -#: rhodecode/templates/admin/users_groups/users_groups.html:62 -msgid "There are no user groups yet" -msgstr "" - -#: rhodecode/templates/base/base.html:42 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 +msgid "Add user" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 +msgid "Users" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:53 +msgid "Password confirmation" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:5 #, python-format -msgid "Server instance: %s" -msgstr "" - -#: rhodecode/templates/base/base.html:52 -msgid "Report a bug" -msgstr "" - -#: rhodecode/templates/base/base.html:121 -#: rhodecode/templates/data_table/_dt_elements.html:9 -#: rhodecode/templates/data_table/_dt_elements.html:11 -#: rhodecode/templates/data_table/_dt_elements.html:13 -#: rhodecode/templates/summary/summary.html:8 -msgid "Summary" -msgstr "" - -#: rhodecode/templates/base/base.html:122 -#: rhodecode/templates/changelog/changelog.html:15 -#: rhodecode/templates/data_table/_dt_elements.html:17 -#: rhodecode/templates/data_table/_dt_elements.html:19 -#: rhodecode/templates/data_table/_dt_elements.html:21 -msgid "Changelog" -msgstr "" - -#: rhodecode/templates/base/base.html:123 -#: rhodecode/templates/data_table/_dt_elements.html:25 -#: rhodecode/templates/data_table/_dt_elements.html:27 -#: rhodecode/templates/data_table/_dt_elements.html:29 -#: rhodecode/templates/files/files.html:12 -msgid "Files" -msgstr "" - -#: rhodecode/templates/base/base.html:125 -msgid "Switch To" -msgstr "" - -#: rhodecode/templates/base/base.html:127 -#: rhodecode/templates/base/base.html:279 -msgid "loading..." -msgstr "" - -#: rhodecode/templates/base/base.html:131 -msgid "Options" -msgstr "" - -#: rhodecode/templates/base/base.html:137 -#: rhodecode/templates/forks/forks_data.html:21 -msgid "Compare fork" -msgstr "" - -#: rhodecode/templates/base/base.html:139 -#: rhodecode/templates/base/base.html:312 -#: rhodecode/templates/search/search.html:14 -#: rhodecode/templates/search/search.html:54 -msgid "Search" -msgstr "" - -#: rhodecode/templates/base/base.html:145 -msgid "Lock" -msgstr "" - -#: rhodecode/templates/base/base.html:153 -msgid "Follow" -msgstr "" - -#: rhodecode/templates/base/base.html:154 -msgid "Unfollow" -msgstr "" - -#: rhodecode/templates/base/base.html:157 -#: rhodecode/templates/data_table/_dt_elements.html:33 -#: rhodecode/templates/data_table/_dt_elements.html:35 -#: rhodecode/templates/data_table/_dt_elements.html:37 -#: rhodecode/templates/data_table/_dt_elements.html:74 -#: rhodecode/templates/forks/fork.html:9 -msgid "Fork" -msgstr "" - -#: rhodecode/templates/base/base.html:159 -msgid "Create Pull Request" -msgstr "" - -#: rhodecode/templates/base/base.html:165 -msgid "Show Pull Requests" -msgstr "" - -#: rhodecode/templates/base/base.html:165 -msgid "Pull Requests" -msgstr "" - -#: rhodecode/templates/base/base.html:202 -msgid "Not logged in" -msgstr "" - -#: rhodecode/templates/base/base.html:209 -msgid "Login to your account" -msgstr "" - -#: rhodecode/templates/base/base.html:232 -msgid "Forgot password ?" -msgstr "" - -#: rhodecode/templates/base/base.html:255 -msgid "Log Out" -msgstr "" - -#: rhodecode/templates/base/base.html:274 -msgid "Switch repository" -msgstr "" - -#: rhodecode/templates/base/base.html:286 -msgid "Show recent activity" -msgstr "" - -#: rhodecode/templates/base/base.html:287 -#: rhodecode/templates/journal/journal.html:4 -msgid "Journal" -msgstr "" - -#: rhodecode/templates/base/base.html:298 -msgid "Show public gists" -msgstr "" - -#: rhodecode/templates/base/base.html:303 -msgid "All public gists" -msgstr "" - -#: rhodecode/templates/base/base.html:305 -msgid "My public gists" -msgstr "" - -#: rhodecode/templates/base/base.html:306 -msgid "My private gists" -msgstr "" - -#: rhodecode/templates/base/base.html:311 -msgid "Search in repositories" -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:14 -msgid "Inherit default permissions" -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:18 +msgid "%s user settings" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 #, python-format msgid "" -"Select to inherit permissions from %s settings. With this selected below " -"options does not apply." -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:26 +"This user is in an external Source of Record (%s); some details cannot be" +" managed here." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 +msgid "New password confirmation" +msgstr "" + +#: kallithea/templates/admin/users/users.html:5 +msgid "Users administration" +msgstr "" + +#: kallithea/templates/admin/users/users.html:13 +msgid "users" +msgstr "" + +#: kallithea/templates/admin/users/users.html:54 +msgid "Firstname" +msgstr "" + +#: kallithea/templates/admin/users/users.html:55 +msgid "Lastname" +msgstr "" + +#: kallithea/templates/admin/users/users.html:56 +msgid "Last login" +msgstr "" + +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "" + +#: kallithea/templates/base/base.html:37 +#, python-format +msgid "Server instance: %s" +msgstr "" + +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 +msgid "Summary" +msgstr "" + +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 +msgid "Changelog" +msgstr "" + +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 +msgid "Files" +msgstr "" + +#: kallithea/templates/base/base.html:149 +msgid "Switch To" +msgstr "" + +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 +msgid "Options" +msgstr "" + +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 +msgid "Compare fork" +msgstr "" + +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 +msgid "Search" +msgstr "" + +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "" + +#: kallithea/templates/base/base.html:176 +msgid "Lock" +msgstr "" + +#: kallithea/templates/base/base.html:184 +msgid "Follow" +msgstr "" + +#: kallithea/templates/base/base.html:185 +msgid "Unfollow" +msgstr "" + +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 +msgid "Fork" +msgstr "" + +#: kallithea/templates/base/base.html:190 +msgid "Create Pull Request" +msgstr "" + +#: kallithea/templates/base/base.html:196 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "" + +#: kallithea/templates/base/base.html:233 +msgid "Not logged in" +msgstr "" + +#: kallithea/templates/base/base.html:240 +msgid "Login to your account" +msgstr "" + +#: kallithea/templates/base/base.html:263 +msgid "Forgot password ?" +msgstr "" + +#: kallithea/templates/base/base.html:286 +msgid "Log Out" +msgstr "" + +#: kallithea/templates/base/base.html:311 +msgid "Show recent activity" +msgstr "" + +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 +msgid "Journal" +msgstr "" + +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "" + +#: kallithea/templates/base/base.html:323 +msgid "Show public gists" +msgstr "" + +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "" + +#: kallithea/templates/base/base.html:328 +msgid "All public gists" +msgstr "" + +#: kallithea/templates/base/base.html:330 +msgid "My public gists" +msgstr "" + +#: kallithea/templates/base/base.html:331 +msgid "My private gists" +msgstr "" + +#: kallithea/templates/base/base.html:336 +msgid "Search in repositories" +msgstr "" + +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:19 +#, python-format +msgid "" +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:28 msgid "Create repositories" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:30 +#: kallithea/templates/base/default_perms_box.html:33 msgid "Select this option to allow repository creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:35 +#: kallithea/templates/base/default_perms_box.html:40 msgid "Create user groups" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:39 +#: kallithea/templates/base/default_perms_box.html:45 msgid "Select this option to allow user group creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:44 +#: kallithea/templates/base/default_perms_box.html:52 msgid "Fork repositories" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:48 +#: kallithea/templates/base/default_perms_box.html:57 msgid "Select this option to allow repository forking for this user" msgstr "" -#: rhodecode/templates/base/perms_summary.html:11 +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:22 msgid "No permissions defined yet" msgstr "" -#: rhodecode/templates/base/perms_summary.html:19 -#: rhodecode/templates/base/perms_summary.html:38 +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 msgid "Permission" msgstr "" -#: rhodecode/templates/base/perms_summary.html:20 -#: rhodecode/templates/base/perms_summary.html:39 +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 msgid "Edit Permission" msgstr "" -#: rhodecode/templates/base/root.html:43 +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 #, fuzzy msgid "Add another comment" msgstr "" -#: rhodecode/templates/base/root.html:44 -#: rhodecode/templates/data_table/_dt_elements.html:147 +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 msgid "Stop following this repository" msgstr "" -#: rhodecode/templates/base/root.html:45 +#: kallithea/templates/base/root.html:47 msgid "Start following this repository" msgstr "" -#: rhodecode/templates/base/root.html:46 +#: kallithea/templates/base/root.html:48 msgid "Group" msgstr "" -#: rhodecode/templates/base/root.html:47 +#: kallithea/templates/base/root.html:49 msgid "members" msgstr "" -#: rhodecode/templates/base/root.html:48 -#: rhodecode/templates/pullrequests/pullrequest.html:203 +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 msgid "Loading ..." msgstr "" -#: rhodecode/templates/base/root.html:49 +#: kallithea/templates/base/root.html:51 +msgid "loading ..." +msgstr "" + +#: kallithea/templates/base/root.html:52 msgid "Search truncated" msgstr "" -#: rhodecode/templates/base/root.html:50 +#: kallithea/templates/base/root.html:53 msgid "No matching files" msgstr "" -#: rhodecode/templates/base/root.html:51 -#: rhodecode/templates/changelog/changelog.html:45 +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 msgid "Open new pull request" msgstr "" -#: rhodecode/templates/base/root.html:52 +#: kallithea/templates/base/root.html:55 msgid "Open new pull request for selected changesets" msgstr "" -#: rhodecode/templates/base/root.html:53 +#: kallithea/templates/base/root.html:56 msgid "Show selected changesets __S -> __E" msgstr "" -#: rhodecode/templates/base/root.html:54 +#: kallithea/templates/base/root.html:57 msgid "Show selected changeset __S" msgstr "" -#: rhodecode/templates/base/root.html:55 +#: kallithea/templates/base/root.html:58 msgid "Selection link" msgstr "" -#: rhodecode/templates/base/root.html:56 -#: rhodecode/templates/changeset/diff_block.html:8 +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 msgid "Collapse diff" msgstr "" -#: rhodecode/templates/base/root.html:57 +#: kallithea/templates/base/root.html:60 msgid "Expand diff" msgstr "" -#: rhodecode/templates/base/root.html:58 -msgid "Failed to remoke permission" -msgstr "" - -#: rhodecode/templates/bookmarks/bookmarks.html:5 +#: kallithea/templates/base/root.html:61 +msgid "Failed to revoke permission" +msgstr "" + +#: kallithea/templates/base/root.html:62 +msgid "confirm to revoke permission for {0}: {1} ?" +msgstr "" + +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:5 #, python-format msgid "%s Bookmarks" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:26 -msgid "Compare bookmarks" -msgstr "" - -#: rhodecode/templates/bookmarks/bookmarks.html:51 -#: rhodecode/templates/bookmarks/bookmarks_data.html:8 -#: rhodecode/templates/branches/branches.html:50 -#: rhodecode/templates/branches/branches_data.html:8 -#: rhodecode/templates/changelog/changelog_summary_data.html:8 -#: rhodecode/templates/tags/tags.html:51 -#: rhodecode/templates/tags/tags_data.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 msgid "Author" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:52 -#: rhodecode/templates/bookmarks/bookmarks_data.html:9 -#: rhodecode/templates/branches/branches.html:51 -#: rhodecode/templates/branches/branches_data.html:9 -#: rhodecode/templates/changelog/changelog_summary_data.html:5 -#: rhodecode/templates/tags/tags.html:52 -#: rhodecode/templates/tags/tags_data.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 msgid "Revision" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:54 -#: rhodecode/templates/bookmarks/bookmarks_data.html:10 -#: rhodecode/templates/branches/branches.html:53 -#: rhodecode/templates/branches/branches_data.html:10 -#: rhodecode/templates/tags/tags.html:54 -#: rhodecode/templates/tags/tags_data.html:10 -msgid "Compare" -msgstr "" - -#: rhodecode/templates/branches/branches.html:5 +#: kallithea/templates/branches/branches.html:5 #, python-format msgid "%s Branches" msgstr "" -#: rhodecode/templates/branches/branches.html:26 -msgid "Compare branches" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:6 +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 #, python-format msgid "%s Changelog" msgstr "" -#: rhodecode/templates/changelog/changelog.html:19 +#: kallithea/templates/changelog/changelog.html:21 #, python-format msgid "showing %d out of %d revision" msgid_plural "showing %d out of %d revisions" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changelog/changelog.html:39 +#: kallithea/templates/changelog/changelog.html:43 msgid "Clear selection" msgstr "" -#: rhodecode/templates/changelog/changelog.html:42 -#: rhodecode/templates/forks/forks_data.html:19 +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 #, python-format msgid "Compare fork with %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:42 -msgid "Compare fork with parent" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:78 -#: rhodecode/templates/changelog/changelog_summary_data.html:28 +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 #, python-format -msgid "Click to open associated pull request #%s" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:102 -#: rhodecode/templates/summary/summary.html:403 -msgid "Show more" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:115 -#: rhodecode/templates/changelog/changelog_summary_data.html:50 -#: rhodecode/templates/changeset/changeset.html:107 -#: rhodecode/templates/changeset/changeset_range.html:86 +msgid "" +"Changeset status: %s\n" +"Click to open associated pull request #%s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 +#, python-format +msgid "Changeset status: %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:114 +msgid "Changeset has comments" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 #, python-format msgid "Bookmark %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:121 -#: rhodecode/templates/changelog/changelog_summary_data.html:56 -#: rhodecode/templates/changeset/changeset.html:113 -#: rhodecode/templates/changeset/changeset_range.html:92 +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 #, python-format msgid "Tag %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:126 -#: rhodecode/templates/changelog/changelog_summary_data.html:61 -#: rhodecode/templates/changeset/changeset.html:117 -#: rhodecode/templates/changeset/changeset_range.html:96 +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 #, python-format msgid "Branch %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:286 +#: kallithea/templates/changelog/changelog.html:299 msgid "There are no changes yet" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:4 -#: rhodecode/templates/changeset/changeset.html:91 +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 msgid "Removed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:5 -#: rhodecode/templates/changeset/changeset.html:92 +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 #, fuzzy msgid "Changed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:6 -#: rhodecode/templates/changeset/changeset.html:93 +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 msgid "Added" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:8 -#: rhodecode/templates/changelog/changelog_details.html:9 -#: rhodecode/templates/changelog/changelog_details.html:10 -#: rhodecode/templates/changeset/changeset.html:95 -#: rhodecode/templates/changeset/changeset.html:96 -#: rhodecode/templates/changeset/changeset.html:97 +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 #, python-format msgid "Affected %s files" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:6 -#: rhodecode/templates/files/files_add.html:75 -#: rhodecode/templates/files/files_edit.html:61 +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 msgid "Commit message" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/changelog/changelog_summary_data.html:7 msgid "Age" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/changelog/changelog_summary_data.html:9 msgid "Refs" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:86 -msgid "Add or upload files directly via RhodeCode" -msgstr "" - -#: rhodecode/templates/changelog/changelog_summary_data.html:89 -#: rhodecode/templates/files/files_add.html:38 -#: rhodecode/templates/files/files_browser.html:31 -msgid "Add new file" -msgstr "" - -#: rhodecode/templates/changelog/changelog_summary_data.html:95 +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:95 msgid "Push new repo" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:103 +#: kallithea/templates/changelog/changelog_summary_data.html:103 msgid "Existing repository?" msgstr "" -#: rhodecode/templates/changeset/changeset.html:6 +#: kallithea/templates/changeset/changeset.html:6 #, python-format msgid "%s Changeset" msgstr "" -#: rhodecode/templates/changeset/changeset.html:39 -msgid "No parents" -msgstr "" - -#: rhodecode/templates/changeset/changeset.html:49 -msgid "No children" -msgstr "" - -#: rhodecode/templates/changeset/changeset.html:62 -#: rhodecode/templates/changeset/changeset_file_comment.html:20 -#: rhodecode/templates/changeset/changeset_range.html:44 +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 msgid "Changeset status" msgstr "" -#: rhodecode/templates/changeset/changeset.html:67 -#: rhodecode/templates/changeset/diff_block.html:22 +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 msgid "Raw diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:68 +#: kallithea/templates/changeset/changeset.html:58 msgid "Patch diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:69 -#: rhodecode/templates/changeset/diff_block.html:23 +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 msgid "Download diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "(%d inline)" msgid_plural "(%d inline)" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:103 -#: rhodecode/templates/changeset/changeset_range.html:82 +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 msgid "merge" msgstr "" -#: rhodecode/templates/changeset/changeset.html:126 -#: rhodecode/templates/compare/compare_diff.html:40 -#: rhodecode/templates/pullrequests/pullrequest_show.html:113 +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 #, python-format msgid "%s file changed" msgid_plural "%s files changed" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:128 -#: rhodecode/templates/compare/compare_diff.html:42 -#: rhodecode/templates/pullrequests/pullrequest_show.html:115 +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 #, python-format msgid "%s file changed with %s insertions and %s deletions" msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Showing a huge diff might take some time and resources" msgstr "" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Show full diff" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:30 +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 #, python-format -msgid "Status change on pull request #%s" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:32 +msgid "Vote on pull request #%s" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 #, python-format msgid "Comment on pull request #%s" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:55 +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Status change on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Comment on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:63 msgid "Submitting..." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:58 +#: kallithea/templates/changeset/changeset_file_comment.html:66 msgid "Commenting on line {1}." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:59 -#: rhodecode/templates/changeset/changeset_file_comment.html:145 +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 #, python-format msgid "Comments parsed using %s syntax with %s support." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:61 -#: rhodecode/templates/changeset/changeset_file_comment.html:147 -msgid "Use @username inside this text to send notification to this RhodeCode user" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:65 -#: rhodecode/templates/changeset/changeset_file_comment.html:152 +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 #, fuzzy msgid "Preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:72 -#: rhodecode/templates/changeset/changeset_file_comment.html:170 +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 msgid "Comment preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:80 -#: rhodecode/templates/changeset/changeset_file_comment.html:177 -#: rhodecode/templates/email_templates/changeset_comment.html:16 -#: rhodecode/templates/email_templates/pull_request_comment.html:16 +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 msgid "Comment" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:81 -msgid "Cancel" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "You need to be logged in to comment." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "Login now" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:92 +#: kallithea/templates/changeset/changeset_file_comment.html:100 msgid "Hide" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:149 -msgid "Change status" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:179 -msgid "Comment and close" -msgstr "" - -#: rhodecode/templates/changeset/changeset_range.html:5 +#: kallithea/templates/changeset/changeset_file_comment.html:159 +msgid "Vote for pull request status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:161 +msgid "Change changeset status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:179 +msgid "Close (when approved or rejected)" +msgstr "" + +#: kallithea/templates/changeset/changeset_range.html:5 #, python-format msgid "%s Changesets" msgstr "" -#: rhodecode/templates/changeset/changeset_range.html:52 +#: kallithea/templates/changeset/changeset_range.html:59 msgid "Files affected" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:21 +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 msgid "Show full diff for this file" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:29 +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Show full side-by-side diff for this file" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:38 msgid "Show inline comments" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:53 +#: kallithea/templates/changeset/diff_block.html:62 msgid "Show file at latest version in this repo" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:54 +#: kallithea/templates/changeset/diff_block.html:64 msgid "Show file at initial version in this repo" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:4 +#: kallithea/templates/compare/compare_cs.html:4 msgid "No changesets" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:32 +#: kallithea/templates/compare/compare_cs.html:8 msgid "Ancestor" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:5 +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 #, fuzzy, python-format msgid "%s Compare" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:9 +#: kallithea/templates/compare/compare_diff.html:16 msgid "Compare revisions" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:33 -#: rhodecode/templates/pullrequests/pullrequest_show.html:106 +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 #, python-format msgid "Showing %s commit" msgid_plural "Showing %s commits" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/compare/compare_diff.html:48 -#: rhodecode/templates/pullrequests/pullrequest_show.html:121 +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 msgid "No files" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -msgid "confirm to show potentially huge diff" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:54 -#: rhodecode/templates/summary/summary.html:69 +#: kallithea/templates/data_table/_dt_elements.html:63 msgid "Mercurial repository" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:56 -#: rhodecode/templates/summary/summary.html:72 +#: kallithea/templates/data_table/_dt_elements.html:65 msgid "Git repository" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:74 -#, python-format -msgid "Fork of %s" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:88 +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:96 msgid "No changesets yet" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:95 -#: rhodecode/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 #, python-format msgid "Subscribe to %s rss feed" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:103 -#: rhodecode/templates/data_table/_dt_elements.html:105 +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 #, python-format msgid "Subscribe to %s atom feed" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:122 -#, python-format -msgid "Confirm to delete this repository: %s" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:137 -#, python-format -msgid "Confirm to delete this user: %s" -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:4 -#: rhodecode/templates/email_templates/pull_request.html:4 -#: rhodecode/templates/email_templates/pull_request_comment.html:4 -msgid "URL" -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:6 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:6 #, python-format msgid "%s commented on a %s changeset." msgstr "" -#: rhodecode/templates/email_templates/changeset_comment.html:14 +#: kallithea/templates/email_templates/changeset_comment.html:9 msgid "The changeset status was changed to" msgstr "" -#: rhodecode/templates/email_templates/main.html:8 -msgid "This is a notification from RhodeCode." -msgstr "" - -#: rhodecode/templates/email_templates/password_reset.html:4 +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:4 #, python-format msgid "Hello %s" msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:5 +#: kallithea/templates/email_templates/password_reset.html:5 msgid "We received a request to create a new password for your account." msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:6 +#: kallithea/templates/email_templates/password_reset.html:6 msgid "You can generate it by clicking following URL" msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:10 +#: kallithea/templates/email_templates/password_reset.html:10 msgid "Please ignore this email if you did not request a new password ." msgstr "" -#: rhodecode/templates/email_templates/pull_request.html:6 +#: kallithea/templates/email_templates/pull_request.html:6 #, python-format msgid "" "%s opened a pull request for repository %s and wants you to review " "changes." msgstr "" -#: rhodecode/templates/email_templates/pull_request.html:8 -#: rhodecode/templates/pullrequests/pullrequest.html:34 -#: rhodecode/templates/pullrequests/pullrequest_data.html:14 -#: rhodecode/templates/pullrequests/pullrequest_show.html:25 +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 msgid "Title" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:6 +#: kallithea/templates/email_templates/pull_request_comment.html:6 #, python-format msgid "%s commented on pull request \"%s\"" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:10 +#: kallithea/templates/email_templates/pull_request_comment.html:10 msgid "Pull request was closed with status" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:12 +#: kallithea/templates/email_templates/pull_request_comment.html:12 msgid "Pull request changed status" msgstr "" -#: rhodecode/templates/email_templates/registration.html:6 +#: kallithea/templates/email_templates/registration.html:6 msgid "View this user here" msgstr "" -#: rhodecode/templates/errors/error_document.html:55 +#: kallithea/templates/errors/error_document.html:47 #, python-format msgid "You will be redirected to %s in %s seconds" msgstr "" -#: rhodecode/templates/files/file_diff.html:4 +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 +msgid "File diff" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:58 +msgid "ignore white space" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:59 +msgid "turn on edit mode" +msgstr "" + +#: kallithea/templates/files/file_diff.html:4 #, fuzzy, python-format msgid "%s File Diff" msgstr "" -#: rhodecode/templates/files/file_diff.html:8 -msgid "File diff" -msgstr "" - -#: rhodecode/templates/files/files.html:4 -#: rhodecode/templates/files/files.html:76 +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 #, fuzzy, python-format msgid "%s Files" msgstr "" -#: rhodecode/templates/files/files.html:30 -#: rhodecode/templates/files/files_add.html:31 -#: rhodecode/templates/files/files_edit.html:31 -msgid "Branch" -msgstr "" - -#: rhodecode/templates/files/files_add.html:4 +#: kallithea/templates/files/files_add.html:4 #, fuzzy, python-format msgid "%s Files Add" msgstr "" -#: rhodecode/templates/files/files_add.html:19 -msgid "Add file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:43 -msgid "File Name" -msgstr "" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:56 -msgid "or" -msgstr "" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:52 -msgid "Upload file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:56 -msgid "Create new file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:61 -#: rhodecode/templates/files/files_edit.html:37 -#: rhodecode/templates/files/files_ypjax.html:3 +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" +msgstr "" + +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 msgid "Location" msgstr "" -#: rhodecode/templates/files/files_add.html:65 -msgid "use / to separate directories" -msgstr "" - -#: rhodecode/templates/files/files_add.html:79 -#: rhodecode/templates/files/files_edit.html:65 +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 +msgid "or" +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:58 +msgid "New file mode" +msgstr "" + +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 msgid "Commit changes" msgstr "" -#: rhodecode/templates/files/files_browser.html:13 -msgid "View" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:14 +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:14 msgid "Previous revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:16 +#: kallithea/templates/files/files_browser.html:16 msgid "Next revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:23 +#: kallithea/templates/files/files_browser.html:22 msgid "Follow current branch" msgstr "" -#: rhodecode/templates/files/files_browser.html:27 -msgid "Search file list" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:35 +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:29 msgid "Loading file list..." msgstr "" -#: rhodecode/templates/files/files_browser.html:48 +#: kallithea/templates/files/files_browser.html:42 msgid "Size" msgstr "" -#: rhodecode/templates/files/files_browser.html:49 +#: kallithea/templates/files/files_browser.html:43 msgid "Mimetype" msgstr "" -#: rhodecode/templates/files/files_browser.html:50 +#: kallithea/templates/files/files_browser.html:44 msgid "Last Revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:51 +#: kallithea/templates/files/files_browser.html:45 msgid "Last modified" msgstr "" -#: rhodecode/templates/files/files_browser.html:52 +#: kallithea/templates/files/files_browser.html:46 msgid "Last committer" msgstr "" -#: rhodecode/templates/files/files_edit.html:4 +#: kallithea/templates/files/files_delete.html:4 #, fuzzy, python-format -msgid "%s Files Edit" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:19 +msgid "%s Files Delete" +msgstr "" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:4 +#, fuzzy, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:25 msgid "Edit file" msgstr "" -#: rhodecode/templates/files/files_edit.html:47 -#: rhodecode/templates/files/files_source.html:23 -msgid "Show annotation" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:49 -#: rhodecode/templates/files/files_source.html:26 -msgid "Download as raw" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:52 +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:58 msgid "Source" msgstr "" -#: rhodecode/templates/files/files_edit.html:57 +#: kallithea/templates/files/files_edit.html:63 msgid "Editing file" msgstr "" -#: rhodecode/templates/files/files_history_box.html:2 -msgid "History" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:9 -msgid "Diff to revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:10 -#, fuzzy -msgid "Show at revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:11 -msgid "Show full history" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:16 +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 #, fuzzy, python-format msgid "%s author" msgid_plural "%s authors" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/files/files_source.html:6 -msgid "Load file history" -msgstr "" - -#: rhodecode/templates/files/files_source.html:21 -msgid "Show source" -msgstr "" - -#: rhodecode/templates/files/files_source.html:29 +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:8 +#, fuzzy +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:11 +#, fuzzy +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" +msgstr "" + +#: kallithea/templates/files/files_source.html:38 #, python-format -msgid "Edit on branch:%s" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 -msgid "Edit on branch:?" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 +msgid "Edit on Branch:%s" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "" + +#: kallithea/templates/files/files_source.html:44 msgid "Editing files allowed only when on branch head revision" msgstr "" -#: rhodecode/templates/files/files_source.html:46 +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:61 #, python-format msgid "Binary file (%s)" msgstr "" -#: rhodecode/templates/files/files_source.html:55 +#: kallithea/templates/files/files_source.html:71 msgid "File is too big to display" msgstr "" -#: rhodecode/templates/files/files_ypjax.html:5 +#: kallithea/templates/files/files_ypjax.html:5 msgid "annotation" msgstr "" -#: rhodecode/templates/files/files_ypjax.html:15 -msgid "Go back" -msgstr "" - -#: rhodecode/templates/files/files_ypjax.html:16 +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:24 msgid "No files at given path" msgstr "" -#: rhodecode/templates/followers/followers.html:5 +#: kallithea/templates/followers/followers.html:5 #, python-format msgid "%s Followers" msgstr "" -#: rhodecode/templates/followers/followers.html:9 -#: rhodecode/templates/summary/summary.html:183 -#: rhodecode/templates/summary/summary.html:184 +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 msgid "Followers" msgstr "" -#: rhodecode/templates/followers/followers_data.html:12 +#: kallithea/templates/followers/followers_data.html:12 msgid "Started following -" msgstr "" -#: rhodecode/templates/forks/fork.html:5 -#, python-format -msgid "%s Fork" -msgstr "" - -#: rhodecode/templates/forks/fork.html:28 +#: kallithea/templates/forks/fork.html:5 +#, fuzzy, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:30 msgid "Fork name" msgstr "" -#: rhodecode/templates/forks/fork.html:65 +#: kallithea/templates/forks/fork.html:71 msgid "Private" msgstr "" -#: rhodecode/templates/forks/fork.html:74 +#: kallithea/templates/forks/fork.html:80 msgid "Copy permissions" msgstr "" -#: rhodecode/templates/forks/fork.html:78 +#: kallithea/templates/forks/fork.html:84 msgid "Copy permissions from forked repository" msgstr "" -#: rhodecode/templates/forks/fork.html:84 +#: kallithea/templates/forks/fork.html:90 msgid "Update after clone" msgstr "" -#: rhodecode/templates/forks/fork.html:88 +#: kallithea/templates/forks/fork.html:94 msgid "Checkout source after making a clone" msgstr "" -#: rhodecode/templates/forks/fork.html:93 -msgid "Fork this repository" -msgstr "" - -#: rhodecode/templates/forks/forks.html:5 +#: kallithea/templates/forks/fork.html:99 +#, fuzzy +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 #, python-format msgid "%s Forks" msgstr "" -#: rhodecode/templates/forks/forks.html:9 -#: rhodecode/templates/summary/summary.html:189 -#: rhodecode/templates/summary/summary.html:190 +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 msgid "Forks" msgstr "" -#: rhodecode/templates/forks/forks_data.html:17 +#: kallithea/templates/forks/forks_data.html:17 msgid "Forked" msgstr "" -#: rhodecode/templates/forks/forks_data.html:42 +#: kallithea/templates/forks/forks_data.html:42 msgid "There are no forks yet" msgstr "" -#: rhodecode/templates/journal/journal.html:21 +#: kallithea/templates/journal/journal.html:24 msgid "ATOM journal feed" msgstr "" -#: rhodecode/templates/journal/journal.html:22 +#: kallithea/templates/journal/journal.html:25 msgid "RSS journal feed" msgstr "" -#: rhodecode/templates/journal/journal.html:32 -msgid "Refresh" -msgstr "" - -#: rhodecode/templates/journal/journal.html:35 -#: rhodecode/templates/journal/public_journal.html:24 -msgid "ATOM feed" -msgstr "" - -#: rhodecode/templates/journal/journal.html:51 -msgid "Watched" -msgstr "" - -#: rhodecode/templates/journal/journal_data.html:55 +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "" + +#: kallithea/templates/journal/journal_data.html:55 msgid "No entries yet" msgstr "" -#: rhodecode/templates/journal/public_journal.html:4 -#: rhodecode/templates/journal/public_journal.html:21 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 msgid "Public Journal" msgstr "" -#: rhodecode/templates/journal/public_journal.html:13 +#: kallithea/templates/journal/public_journal.html:16 msgid "ATOM public journal feed" msgstr "" -#: rhodecode/templates/journal/public_journal.html:14 +#: kallithea/templates/journal/public_journal.html:17 msgid "RSS public journal feed" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:4 -#: rhodecode/templates/pullrequests/pullrequest.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 msgid "New pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:25 -msgid "Create new pull request" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.html:47 +#: kallithea/templates/pullrequests/pullrequest.html:44 msgid "Write a short description on this pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:53 +#: kallithea/templates/pullrequests/pullrequest.html:50 msgid "Changeset flow" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:60 -#: rhodecode/templates/pullrequests/pullrequest_show.html:65 +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 msgid "Origin repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:85 -msgid "Send pull request" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.html:94 -#: rhodecode/templates/pullrequests/pullrequest_show.html:137 +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 msgid "Pull request reviewers" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:103 -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 msgid "owner" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:115 +#: kallithea/templates/pullrequests/pullrequest.html:114 msgid "Add reviewer to this pull request." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:129 +#: kallithea/templates/pullrequests/pullrequest.html:128 msgid "Detailed compare view" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:150 +#: kallithea/templates/pullrequests/pullrequest.html:149 msgid "Destination repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:4 +#: kallithea/templates/pullrequests/pullrequest_show.html:4 #, python-format msgid "%s Pull Request #%s" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:35 +#: kallithea/templates/pullrequests/pullrequest_show.html:36 msgid "Review status" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:40 -msgid "Pull request status" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 +msgid "Pull request status calculated from votes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:56 msgid "Still not reviewed by" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:60 #, python-format msgid "%d reviewer" msgid_plural "%d reviewers" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:62 msgid "Pull request was reviewed by all reviewers" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:89 -msgid "Created on" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:102 -msgid "Compare view" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 +msgid "Pull changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:116 #, fuzzy msgid "reviewer" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:164 +#: kallithea/templates/pullrequests/pullrequest_show.html:133 msgid "Add or remove reviewer to this pull request." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:168 +#: kallithea/templates/pullrequests/pullrequest_show.html:137 #, fuzzy -msgid "Save changes" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:4 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 +msgid "Compare view" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 #, python-format msgid "%s Pull Requests" msgstr "" -#: rhodecode/templates/search/search.html:6 -msgid "Search repository" -msgstr "" - -#: rhodecode/templates/search/search.html:8 -#: rhodecode/templates/search/search.html:16 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 +#, python-format +msgid "Pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 +#, python-format +msgid "Pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 +msgid "Hide closed pull requests" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 +msgid "Show closed pull requests too" +msgstr "" + +#: kallithea/templates/search/search.html:6 +#, fuzzy, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 msgid "Search in all repositories" msgstr "" -#: rhodecode/templates/search/search.html:50 +#: kallithea/templates/search/search.html:53 msgid "Search term" msgstr "" -#: rhodecode/templates/search/search.html:62 +#: kallithea/templates/search/search.html:65 msgid "Search in" msgstr "" -#: rhodecode/templates/search/search.html:65 +#: kallithea/templates/search/search.html:68 msgid "File contents" msgstr "" -#: rhodecode/templates/search/search.html:66 +#: kallithea/templates/search/search.html:69 msgid "Commit messages" msgstr "" -#: rhodecode/templates/search/search.html:67 +#: kallithea/templates/search/search.html:70 msgid "File names" msgstr "" -#: rhodecode/templates/search/search_commit.html:35 -#: rhodecode/templates/search/search_content.html:21 -#: rhodecode/templates/search/search_path.html:15 +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 msgid "Permission denied" msgstr "" -#: rhodecode/templates/summary/summary.html:4 +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 +#, python-format +msgid "%s ATOM feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 +#, python-format +msgid "%s RSS feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "" + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "" + +#: kallithea/templates/summary/summary.html:4 #, python-format msgid "%s Summary" msgstr "" -#: rhodecode/templates/summary/summary.html:16 -#, python-format -msgid "%s ATOM feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:17 -#, python-format -msgid "%s RSS feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:62 +#: kallithea/templates/summary/summary.html:16 #, python-format msgid "Repository locked by %s" msgstr "" -#: rhodecode/templates/summary/summary.html:64 +#: kallithea/templates/summary/summary.html:18 msgid "Repository unlocked" msgstr "" -#: rhodecode/templates/summary/summary.html:83 -#, python-format -msgid "Non changable ID %s" -msgstr "" - -#: rhodecode/templates/summary/summary.html:88 -msgid "Public" -msgstr "" - -#: rhodecode/templates/summary/summary.html:88 -#: rhodecode/templates/summary/summary.html:89 -msgid "Fork of" -msgstr "" - -#: rhodecode/templates/summary/summary.html:97 -msgid "Remote clone" -msgstr "" - -#: rhodecode/templates/summary/summary.html:117 -msgid "Contact" -msgstr "" - -#: rhodecode/templates/summary/summary.html:131 +#: kallithea/templates/summary/summary.html:76 msgid "Clone url" msgstr "" -#: rhodecode/templates/summary/summary.html:136 +#: kallithea/templates/summary/summary.html:81 msgid "Show by Name" msgstr "" -#: rhodecode/templates/summary/summary.html:137 +#: kallithea/templates/summary/summary.html:82 msgid "Show by ID" msgstr "" -#: rhodecode/templates/summary/summary.html:143 +#: kallithea/templates/summary/summary.html:99 msgid "Trending files" msgstr "" -#: rhodecode/templates/summary/summary.html:151 -#: rhodecode/templates/summary/summary.html:167 -msgid "Enable" -msgstr "" - -#: rhodecode/templates/summary/summary.html:159 +#: kallithea/templates/summary/summary.html:115 msgid "Download" msgstr "" -#: rhodecode/templates/summary/summary.html:163 +#: kallithea/templates/summary/summary.html:119 msgid "There are no downloads yet" msgstr "" -#: rhodecode/templates/summary/summary.html:165 +#: kallithea/templates/summary/summary.html:121 msgid "Downloads are disabled for this repository" msgstr "" -#: rhodecode/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:127 msgid "Download as zip" msgstr "" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "Check this to download archive with subrepos" msgstr "" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "with subrepos" msgstr "" -#: rhodecode/templates/summary/summary.html:197 +#: kallithea/templates/summary/summary.html:163 msgid "Repository Size" msgstr "" -#: rhodecode/templates/summary/summary.html:204 -#: rhodecode/templates/summary/summary.html:206 +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 msgid "Feed" msgstr "" -#: rhodecode/templates/summary/summary.html:224 -msgid "Commit activity by day / author" -msgstr "" - -#: rhodecode/templates/summary/summary.html:232 -msgid "enable" -msgstr "" - -#: rhodecode/templates/summary/summary.html:235 -msgid "Stats gathered: " -msgstr "" - -#: rhodecode/templates/summary/summary.html:256 +#: kallithea/templates/summary/summary.html:193 msgid "Latest changes" msgstr "" -#: rhodecode/templates/summary/summary.html:258 +#: kallithea/templates/summary/summary.html:195 msgid "Quick start" msgstr "" -#: rhodecode/templates/summary/summary.html:272 +#: kallithea/templates/summary/summary.html:209 #, python-format -msgid "Readme file from revision %s" -msgstr "" - -#: rhodecode/templates/summary/summary.html:332 +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:299 #, python-format msgid "Download %s as %s" msgstr "" -#: rhodecode/templates/summary/summary.html:379 -msgid "files" -msgstr "" - -#: rhodecode/templates/summary/summary.html:689 -msgid "commits" -msgstr "" - -#: rhodecode/templates/summary/summary.html:690 -msgid "files added" -msgstr "" - -#: rhodecode/templates/summary/summary.html:691 -msgid "files changed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:692 -msgid "files removed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:694 -msgid "commit" -msgstr "" - -#: rhodecode/templates/summary/summary.html:695 -msgid "file added" -msgstr "" - -#: rhodecode/templates/summary/summary.html:696 -msgid "file changed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:697 -msgid "file removed" -msgstr "" - -#: rhodecode/templates/tags/tags.html:5 +#: kallithea/templates/tags/tags.html:5 #, python-format msgid "%s Tags" msgstr "" -#: rhodecode/templates/tags/tags.html:26 +#: kallithea/templates/tags/tags.html:29 msgid "Compare tags" msgstr "" diff --git a/rhodecode/i18n/fr/LC_MESSAGES/rhodecode.mo b/kallithea/i18n/fr/LC_MESSAGES/kallithea.mo rename from rhodecode/i18n/fr/LC_MESSAGES/rhodecode.mo rename to kallithea/i18n/fr/LC_MESSAGES/kallithea.mo index 1a4d0e96c6e043931bb1f7c4857fb78603ee0328..f0899d1a62c4fcd3ec67031fcfb36482b1ed2646 GIT binary patch literal 81674 zc%1FM2Yg(`)jqtY83>)w+s4EVthK=uTQACfk0@Xx6nf;fzU(Ccg}gv+&g!RWLn<5|1bQoX7BVlbLPxxGxNem ztDPRB|8`p~7TcP_2YwQZ{CDW+SZo~%7gD$*g~wBvpzsC?`%w5Ag@Y(ua}2^=DdZ}e zDcpy`qbb~!!aq{D9)&MZxB-QKqwvQReof&<6mC2=7TcV{eq#~8*I49hqHt{r-LdFL zPQ!&1{)qdd-)Cs}8w%H@@M3<)G z@qS6+b`)+n9`M^~JmAte9__YJ7^iSPg>4j`J0A6|HX#<*rG0TThwSrY-z_KCoQ`4chj<0hj13pD=HiRjl26EW^TPDFp6)AFxQ1fIQ5 z;SM}s`=Z>0eNo?xeSw#03OAwflzmbE63zF!ebMh*_XT`b?2GX{yD#SPL(RA0B;<=v z!aVhxgz@h(3H6QB@2Qh8PDev`68h;)0zPz5*hJwkD7=8eH!1uDg^MO*zP6fz@m@#a z0TkX%;Xt0RsnjNgbrgNN+aMus}XovXawGzNZ|m6S0n1Vr4ev`suA=1RwLHk z*Ntd@?IyIdRTJWW+Jtt7P`Dbe-zL<%m&T9N{Pj&(Uk6b5Q^psKKdlLPaE_L{NyFQl zFphgD+==_q1h{N94fr{68v4^P4dY2p!#EdA!@50w8sKxqG~ngETJD8u=-2DhfQRqv z_gd3Ye&gwYQ=jQr55uRUoypSykAo=OlR}@uI-ZZ|fZvzXL3jGjAR5B(n1OY3^bGXx zni&}PeKW8=|2{+Mv3_s7Kj6Rp{>Z=Q{^;Ly3aRQ?c7N1=&;ID|BN{%pKj_zM`vY#h z4?unEQAkTRw(SABJ`TXT>Yy;k{W<{f`1k=4sGOq}R>Fx|lf=`A*RA zEX}`UCi?k@nV9D%HT;x9kMaL!z^5ZA+@8XVeui~%l zvoKHR&I113F$?g0br$-$`a!6_&q2V;y${0p@&{r49(54laD|399|SzQ{~+N1i~9Y+ zL0CU)%tpSAW+T4OY~Em0KUu(s@6gB?DR_vQgThZQ&tyt%4 zwIP0Z8`f)9!(X%k-Z!>kUB1$W_4OkU`|3~+{hCeTPzq1-kbbAezop@3bC5oE4%+FO z13Gfm9L&#MbAU(B&cXO!pM!D#eGcHh{#@{_ThB%Q-R1(WljdUH+vZ}P+UH`P7t94c zIc6@_?L~6|_bcXNULTnY_&-JA$=sgiE2dHY@HFQ2_%zx(P2(@6@OKnmlLp)mZU=nx z?dZpG?HK>b?Z|&aJH~TIJM!P#4!nJ~9pnF7JK9+#gZ{3SLH~Z5LAf0=n8%$nSRbP^ zfYT&R-#>$P56+-IHv>4#r;t!2wpiS`8UkBiI zQU}KO>kiPNd-eOJ4&c`so#;oOPQYn!C-UvyiSkoBQGcov`+P?y_~AP#97W;Xo#qO0PUZ;0B}8Lf$sa7e)9sr=^jmgLepQ@dOukJIQ(k?_`KB)#Xh>tp-A8BP{4D- zp@2)%q3CzZp%~AhhoZjY_4}Md(cWc;qW?D@3jDw8P_+MomVZz4uf7oNY`hTVwq6Lj zw<&Iy7{+y-hmoEgKU9a`ryAb_;O6z}hA?EAdh3LnshoStB z4@3TbhoPUl9)|u+Jq+~7)qIB^hVuWT-%Aez+-^P$Xw0_$z3BOr(Fegx7_JOblA{Rp&o@ezRQA1JJ)@S!6x&b5vNT;oS- zzx8|gk!Wwsk$~^?BLS!8BT@gtBZ0ri9tk>e?vdDMmubG|j|Bbs>`1Jy;YWc^?0poz zk30(FI_@a6bDDntM#C$P0$i3Ih55SUDDZ>NQb?j_Z0OOzgJX|I`Lp%=ilb5fwxiMS zdyYmuj~)%YfAMI*AeW)+b_bp z+i4N{J8BWeRlf-R_}L=BzkLzr<(NgfuPj2n7cIg(-LMFFeE%Zg;h**Uea-*zBH&x^ z#o!C~Sd4KO7o(md7Xz+mEmk_b80{}zjQ;##G3NE2#lW8j7h^n6F9trmtL1wihyJdA z9OR+?$6>rvjzfEMjzj-Cj|2TY^El9l>ooo`&Hv$X=-2wkBkX%T^e7{a$9!~Zc>3|^ z&oT;!GhR@b=J`J!@`if?!o??Gey=zI^4NnX0B#?g0QmGi5%aLciRk~p6H#u|i5O?< zMD%wag%h~l6VcBXC>+o0_C)ZJ`%EqfZ9DEjbx@e#^<|=MyIb&VM@@eC>};zJ z3fejE6qJ8N^SwnOZB?-~Pes0?P6d9Rc`E47l2g(DD>VICrvYy-(D>hI{M8g5Lj2rqrvVR#{1W}y{g>L# zF9FYnUt+xNzf^fn^PQ^UuYL)6^V(m69>1^OHK)g7B$CJGo{n{R-|6Vb)2Cw|o7|#`Fg3jEi-_L3I#+ex3hi76vtag^l8)vD!aTf4ux3fU6 zn$7~g9CnuKZO;N8-k|A^ouzu5vjE?X&PKnsJ{$O!(C=wygHLKb8}#L*voQ}V&IX>o za5n1s^lYr}bKU(u&d@k_%rgPQKa4y#GeOm5g&9}yR7|)jHslMPm zte1Vy13c%Phkh(R4{$!?JdFG5^8nBLG<^L$(4SS$N4~!2qd$9{k8#gFAL&P*kNPh; zANAjTKJew$^D&MeUx0Ay3ozcFUV!--cmeQW=mo&Ty)FP8Mr*!_7ofeV7eLRDy#Vlk z>jL1}x)*|u{q#cc|LF^n|Hcc!|2}mg;IP|8=>L8fVVrX>!h9Zm5z;Tx@aBt9?~@w- z?IOT$wO@fwZ}}^XyXjZZzjXZy^M38GfM0L@3iWUBYsh~Ce+@XC`fIGOJ1M-H*Dr-L zDE!rLz;FHYHyD5ai!r}DUJU%+>0 z0(^OA3GiyoOHgjpO91B`E&=~B?h?SW;}YP@iTZuTC8+<-OE8ZQUV{19{8E%3dMWCk zs^95LQGW5IN(U}Q`5P{Uo@4o?fcqzxVx9EA4D?~=%RtY5b{YCtxD5SYd>P<;zNTMy z8R~oBGW6r=%YZ*0UIw_VyAXEq=+}dnV?JKK9OHiTa^ThKS704&djU;GH zwA1TK;9c)4!H4g5CGhQpE3tq4{z~vCpI!<3%h2DVosQq)`xFYtQ26L?L1#Am9m6z<34z6N+c?;6a@k=Fpv&$|Zo-Es})`;}_|_jRrX9Di~x@MX_y z5kL7_z`I$$JFZ24Ptf?Q_4}@Cf!A+o`02Ii=jzK4{&X42k6woQ_t)>%WtfLUmtlU6 zTn2nRcA3f-%YbLU(eJA?{Z1|Sz%t;$qsuVw&n&|_et8+@}$_>08^kcW{K~H91k9zW&KJR+0t7EPQT&}zx``c~${jk>e zvVOmHJ;wFL^~y)wfc~t11M+Qk1M1)Y2Eb+D4JcQm@q68X@?&oRUQM|Hc)kA(=+B8a z08VG$fch_>kl4D|QZ0X_ws)<5-*yAWb=M85=e$An9$L>QHvleQXt>IaXlJb((XUN! zL_Gs;M86Um?tUZsxA%=GH}OW)x8IH63#V)OU)+fOX^G~4LF3=N5&i$1!a0n;HxW)! zn7ax6|L`XC^Itci{q=v3{%`Vo-M4>_c^&wBr0-7Q!@YNmZub;aGaQomE zwEr*tUiVgfZ+R>FKj2p7yKhB36ZCukTLBO6R@7IxRqbsWo^>ne%Mz{Uc8z~X>v>MY zcWwpzzPJ^1qxWs7f2-RNKj=2l{lnQ0RM5z3c%sf6{!EM73kk*E5P@Cy#o8zu)8pi``raNXYW!wu*P3_7uMOW zccH%z>-W=lf$qG07uM0=?^3L0-RnEL?Q?|cAwf6fCacku(5mt_xtFZ<5*9*8G=0sCJJB!3W%<@$Wo{`Tj`DZS)YrEgk}# z;tzpun*I>z;JFW>y+1vKd3^LCjOW#dFwQR?f<0*MhXJ3RA4YpqA4a*t!&t|MK8$u3 zJ&bWIc^Kudc^GiI<6+GAQx5|kUp$QQum5M*9ezsTFL~Ym8Gaj|{TcP{^9cMkCO-l? z@vBGBzrQ_#{;&Qh*5@vdqP{WueZZrDzxOEU*wK%oKmYS6{55{1@t-}4^}5Dm2seHV zbSC~7#<$O7YG-~7czU4bTk;snU;7yRHSTy!?KY3AzUXn#nTE$vKJ&QBLyx2Ud5@zX zOCLwSVozWlum6PZ3r_%UyFY<>o$>_M>x?HbPo93y*Y6XbK)dHZfqA-C(;t2U>*D1n z(C&s$0&li`68U#}68#+aB=Dp8Nzjk8o`k=~@1I1!w|@%z_^78)-(gRIpZ%T2KmHWT zZ}>F)F2+9%cy&Du{oY+qV;!yg4B$KD8R*R#o>9Dc2IZDKgKxupUrbnDy@dI>^(Dw{kGur>x7N#OcY~KPo^4-7{EiyGvwrXWGUUhcF9Tl3X!x6#fgg8L zcm##dzpVX#1@JiQ71dL{0zAI&70|CQUcva+cop<-(^s({)xN6!kgqCSHC*zl>WMV{ zsaFB#k6y*Rto~Q*FI)c=>uu~`bszjI*2@x&f8wub??JJUPrqBI^xgO@IFod^mX;Kd;@TC-oX4Ud;@s&i#ITD7rudcx%3Ud z{oXggw?6R(_=ESf{HAYW-gkae?dWd;Zd2b>Kaw}qF8`+5<=@2mxc5!q_akq@U*oTD zqFw(j_4jxS^Lor%=--JN|LeEluW{vDn75g4BP_g)ew_3+;Q2pqV?4{>M!gTc4g7lY zZM6IL+p5=nTld>{Fy1ZR0iRa;j?#~JFptyULBCtyLA|+mRG<0|+CBOm^#gtfczMA) z(AQn5^=&^+S6X{u+7B=e>vVi4GatG?%b^sC?d@YfjhKIZMZ_kquMy^nc+QuDw1KIq^( z?*qTr`v?3rcKiqYHCFrsaNYVtjAQVJsAsH(Gd{$+^F9Qh_v;S?82Sb3O*YnfVy~y82^`cg4r* zN3Y>aAEVw+KSsG#K2d%5C#ZMJPmn(76W!N8(S7|B?DsSDyX6z`E!j`hpZ^oAlQTZS zeBG+?_kRMu>8VeEH=BM6xNr5T(zQ>~?#`d8pYf*{{}jzP^Hb30xf-7IDd2Y1r^n_n%>1KCItgeTMnn_@991R{uo%L;i_&_xUIKG4-FI8wY53 z%0B^@yEXmKTJG6@qMz?-`j`6M`*YyyW}oAGz~`uc*yn)z*v~Pqb)W0Gi_Zbqqdy1S zPSSE`f3AKpp98M9Yy5-y{ru;cmv=tLcs~Ce`}z7`06x2Xf$~$nK>n15`7fY9Jp2pL zfg8Vo{^02^(C<&b0KHrDOSJdXFVX*9zC`&^Ut&E^{Zj3+U!wifzf`{eORSq^U!uN0 ze+hWK{3ZJP;g_KIt9*t2_4^9=H1aF-f5un9zeB&$edjB+M}DRD$gj|kTfV|L{`3|4 z+3RcI$A(|4p5<%k@pu0k{u;+>`cq#6KJR@E{8;N>s^9n**5`zO!Jc`fhWGsoc(XyQ zm-J_I3VED6P$>F!3c0m~jEK+`{81^w=|YA=D;dK5B0IDo=~DLi6TjPI3IQT`tkGW}U~ zHPo}|YUua2tD&A9C}h0feKnM;*Kqb~s6Rs?y7>%Mj_L|U-ZU&ou%J5 zY57|zzcry2iHVDo?a7h zd2LP1ORu$hiCnrCg-o}Ht%da2YoXo+YXPoDQ^@<^)oTGyA6pA>{6h2hT^s!xwKn=S zgF-p?LLt+ID>eMn+GzJp3RymWpF;N682Ka2+tMGQorive`TB>(Z@doRHf$Zhd-6IM z-|TgOC)ssS?o`dUY#o%pmqM23-d+do4_z1du;02E*V*f$p1aq@IG$J+>*^otqMfzY zL%FTi!@LZqkm*?yg)9#qqUo2chx~V~hyFZCA=9l-*8`rdw?69KnL?&36E!?q<8NCZ z>-Wj^QUAy51D`h9pqK1p{Wd^)i-yNg$o?7^Z-9K;ZHVAEakI|nsHvzo2*aY)4a1-R;cN4&&c@yNDui*(4vV3zMg)Fx}tKXY#ihfVq6y=s} z3cR|1Q_RC-8voj+824A3VqI*u8Q`%4g}ndnxf$?(9}3xD2-U8(hqLAgF#am#0uh{~4a)+irzXkBV_m-Hqt+zz~`ccUH;?OP8&pG;iD22?= zEZY)z{nnOPx2tW1dbXjE^}aiArSxDc;PCZ7t?@bEXUt_zi(Z0Ji#+lt3 zc(Oplg^0KW&ZvKDss9`zwXK@2|NH#`9Q-)&?94dm*zYK0ed8x_(BFwa=@pws;lV!v9lGHs*e9R*3HG_Q z`ykx459a^iK7iL5ebC-DeNg`+eK7xTQus5*%kA-q z>j(JU-Vgo0s~_O^Vn4w3RSKEU`&&PZe`J5aWmbR8hub^sliy93J4r;zm=$L;{Q|6vEf>zy4y zA3oUu^f107`ZsJxtdB`MVqDISNT0VO>N|Bu^y9o8f$ul&2)MkZIMU!ClAJYJ8CfK`U!)uthrSbuXgJZ(3O zt=G`o9e8=S})rxyJkT8sL|>i3jd^zYzW;IUte{x8ycPOimzIHMN(_-{1-1GO0M zi<2?-t@tA>MaDXPcWD=vT>` zE2h)&yn9H|^{Zs(yk0g#*}JmE%2~2Gm(w$D=StL2ZKrRjBrF*B`aG96ew8z zPIOo;*}R2QafM=~)vACJFj*x$Kc30b;&*a6s-3c@n&UY)-{$0~X9cQ>I?Tw+0OO`I zPCNZ<$!FW+L{BiJE+RDT@m$(zAir3CE_GxVGd==IB6^miOCh4X@n&S&DmlhHY&-(mY{<`#{=elBBa6s zfkTR3-iNd^v8`c$)JBkt-N$9KAyoU-%|)nn2yLtxVB3^ ztpd{s{=p9`o`xAG6b7M}2tu(o%3?MGj-zeNgn~u#At=_K?QjD^&Y&u^(Wq^-PngWb zTsrHdbYZ0koXJAEE8gKbA*>~9K02Cw3E|Sn9$Tc8=%h<*(SRXDQ~q>Q_#1cI9WTvG zlZum{>srd&a2mLXYhB>&c%Ic zX(8yiLSO`5u~DrA^mLm4h5H+S)YZqGREn0UPu0*4#uG}LNlFr(BxqH;Lz_}I15jB2 z6_jkIGK6@9r-XPs6t~08cM*HTM4%Lelt1ORIK^~yt$<|NX$y z>1Fm)&?(!gxWKK4B#^g1qLqZt*msDZBIHQKM`f~^uJ&vZ+TdBHnyiv~D`(b4M&t5OE;D z3*F5olf^tU-KnC~lBDTir0;OjUP{}knpc=ahI0$rsh-tv2%MFen3c+B@2$j ztd-4as9&}GAceluK_As~5drKei;eX?=4CoA91HI)1xD3m4^ttV5Y2qgGhsoM*$R&8 zZbE32$x0@wIUGav{L0;wQP~P)v|1HXl(@%y4`Y^mzHsd;lf9TBFwO46 zi`Zu7BcJj5bg|WAq7sd6G`!^~2qU8`GGpil&!jt#B<)N{R$`+%2+x`6iZ>U%bfJc) z%QO)rwY%-jETK_Mfn-tHX;YrhX{p#gUdCaZV$R6=9Usuw9~d*DY4C$_E|gdIA#N*% z9bE%SH(UHZMdtftLHJ3UX3oXEWTcwx=4qNe8Vd6me!PZ&?y#&xz}!cN5*uAc)GVkY z)u({ag1<5>UpR#4t;#H5V;Fg1(B}YT!8$LIPzmXCX{QTt6+OpF)s#piVwT25ehST$zC%M`De1zFgJpOwGg!+Mnv*T zH!^NagfUtU%2v_0uxVH;hEj|s5t}96v&XY)Mxq?<_zE=S^1 zZg~O-dm?^7wis_G&WFh^A+0UG+LAnt!!>({?o}M)inu|8=g|qV(Vs+Jf?sL=Mc5$f zM%EYzVTTkrN2Ha3$dS?@lvDUS*xb$RF*O!J6DUB7iMZNKP#ISoG(wZq?2$y33991R zjE&Bw(@st?l)l>A9U2%>D#09GI7>~#24(eFk#|@0z!ouvPB=fOWf}w zqB}28Px-}Mj!*?9i84=yn%I15@62a=G*v$(S#+TqTFTWRCYV``XrO_B)i*Ir{39Qx zlNBQCWp9z)(j?}~Dhy%<#hbNx`enMt=u&W6{X~$Tzk&}1bEd`1w?io(P<)MKl7UT4 z*2j1j;;WxYe*)$)Wr>#n9ypy(-A zX?nn#xHiu$vY4HX>0A{k$tV=JBeDbQ;_Zy8t`gojgMCwV-Q}62zYaLt(k`of-c1hB z((WuZOVdAj#@tfCLtCc^Bvxp0E$3&$}80U>se@0a2m18mH%BcXll|}@j*8Y}m zlzvA`$=+MRJTzJ{Dx@mV%Lrc{8xz=Jf?ule8$%o>M79L~c4K2ykwa2-pi2}Mg_S*` zV+pd@b8q4djg%r#w6cD2P{0il$z)+GULYyR$d6to<<1j+jm3v{H{R-Ij70fOD(0sWIe466GeZF0$@~^sV@yT5RV7;WA7e`BQ&~hLA5^kd zV=3K@1eHvbNPm?sH7{7cOZosGe@dl?e@;%?nh2O&CnXjk-E?8MM=|R>&P9Mu- zg_e&;A2rC?irXad?inL|s7?l=v#|4SD#2!yK-S2+=pon1=${nU9}TflDiIS?G5-Pa zlwb9sN=d%U%r+7$NG`vqdGKAe1U8PTifEk37}Olx=qv;#QJTv)5pAs`%MpPPs>C{-3_69> zw3BajF`)7^+L_r>ua-M*5_@XA$(rfFG{UA)XuX*RLu65PI!K*`KO|Hz%Tc`{TM=R9 z;(bLwEvBR_hB}oYKvV-#%7lT6Y;1<5*S-VVz05$5S){x}*qaw_S!~tF;KYdqE4r03 zlJM7Bk~7%?@g_pF%%N(xZeCiO@=m zjA}>Z-K3ZEL|7VISz#|iPPIf!n_r1#=(&_(9#%4E4>eaY1@ur#_7&4ql|0Om^pwYk zmLVz~RL+VGox7Pbdvs43&FMf+qq zX#|cGJ(M9*T_owsFD*5X2})#z?M0C}*}S640gaX2mwtOh<|#BPbXM6{FwaqjywU|f z@)6aWj{|cN3SD9=w_{6m#<6kiw;}#ktZtU&E??3;`Q?Qw$WU8}B&JKq&%bDY7R7Y4 zt7Mxf8N3pBkAmkGJhdFP#^VzXG{!8&TVy^e)-c5@5`)$3ihYuqg;AnKOd6%9@C_ij zPN1>FW+I+8qPC8R!!5+IF`<^G#1|!%pzh>pDNUiV;AcjDi8Gl7fvAfOJQjMIjmxrj zQ}>>dohd#eD;kx618_=gMR6}=s%Y2Dd#x_aupk*+YlP8m?lSHX5Z2w)Ak@yI^m#5M znTM`|GnGhXO_e@(Jl~oP<#;nr1Z@pU-MoBLjQ+BOT2~(%S0aYR#@97bzY6%Fj7@C3h+^rOaE<&Y zvitHTE0Jlhh4u>?hkUWxU1^N(Ws+jfhzpXjgA2I5L|pU*0zRWU0qe?|<-P+Ls|VW5 zEerD6D>UlUUt2K|8=uZLb5|vZ2yzw0zVX@kK2CBjh1phGoTG@IbP1D_%n}PVKCkAN zVm=L?H1LsQlLXi>%|f`-;pT1nm{>dhE&sy`5z^`8J;rd~EXQdLlPnJnA}dLD@gw4w z=iM^h_3ay7;FF}#?k?ot{o4wKTz_V{9w$T*sQ0-=!UD>k>v>UWCOx5*_jUsNIEyL_r#x@M10&PNsiLl29OG7Mr zxm{9~DPP}JXk&d-F=HyqTc-PP!brHT)jl+H zWy#QHsd6V<`-BH*_Oqgg60HK23(9~|5Pr!kB!YgGd7b!y2e8O*9df#W#n_A`#FjD| zOm2<$aZgKOnpmNnX6^}>Yb}!4NL(3Ad4Q2qKZAG#(~76u?7YDatv*^)IZ+Jp#!dimBSXT2M||PI>8z?S9MhpnD8pG?L zIGaJiq1s8jKMe2(4)!}TJL+$-)0zrc%U4#bDt&2PGpE-?({e~LTY!slBFJTlF+x@9 zLL&{-T1F=w;g#yTG3C@*8tvFb^@9rOpE$!(Qr=99HnQ3F7AVsokZT=`@3ko?WVkRY1S8n4S}z|-8< zmyfB%f`pKy#SqAD0DOMPil$kzqp1rSl9BL>>au--Vv~*2X}3;e$d&H0&6nZID0MoD zPoEzXq8}JDOk^0{if7B;Av!mO=dqctWPH;UkXkYM@(sg z;$-nx;g4yS9d5FEv4lQmV~rlwjYbAk7iB z!}MfTYsX~8@*l?TMtBYpKpR{Z4v#6N|(V)>TOaw1g^ zmYGkZ&^EvQ;D^XBMDCQHO=0({0=uQC8=r{?Y%3Cjb!BSL*r*BTFio+X0f^D?G8mdI zRco{dyMVHo+#tu;$f9LW4)KJX$F zu_g&)pBx*IB~45S72}bc&>ow;8mANu^%0A>QP|-mtQ<|VPRX?9y%ckfEzG!6l(BGn zqI2uaBzmr{-O<{@(~&D#VIfN}=x|F|o~i6-S$fL1a;)qO#(-!e=~SE+Z0;iLpbtfS z=ICbnvxG$z;tuCD`(!|%XB2*rW;ZB|W@wvGCZF|g=29q`l1CN^!w9&BhV9QtHx8HQ8sop8rBi zUGEY;84tFYWdyFbSA2#^UA?s#S--I+Lb_W|Y!~5HJN=MF>Z(x>3}Q)SK<-Q8!S~nI zckIFpZC!5qZsC~hoF&6Wk_TBj^p1;rEh2QKs7`o)>+$!9^Ie=KODvTd`0>62K#T|K z`Pu;)+EZp1va>mwBAbbtupWo`{XnZL!m z51(K)_?Q$v-~fLC^-x!-Ghq%M*jjx-78mB*q-GbLi?v&tiX&8-75u^&aHsV+Ue0C8 z!=on7!{alPjvOu&H}W*?@>vm@81qZ3HHN-+tsH z3LPXEd9FTs%q9AXF?l4zb(xf^Ks6cckwnhE*IPb+k&nuUhw4jRa7!c1k?m$t*yFf) zwLBG4%{g&(*pH;C!G@W3xo1Jow(tN)4BM1v-vsEF`jeG452G0+Pab_4Ay@RK1sTl5@r9Sig;A zzh9Bf5Mr~4@f`<|bK4wI={$FX(+LvW;MRax1;nl)K(Ji6p6%EGA1TsF$)9#tbp{xX zI>7by+5M)$ZQ(z-wj(rX1~D1KAjR5%7m8o2Cj7`J`_R1L`ywnvQ;wF zM`Snq15Q)QFY1}L3h9|_H;Hn7s(Lb*nM&y;J8~o~&=W>tgLM&!Ej>cVHfkpIOz_3` zdxWZf;a(moD|gZ4!=q1?Q#+M!2~)eQpKNqssF#}?n1ODM*d-`Wg_41_!edU|4ZL62 z=F5EuEod;dGm&B&GyKu9H^s$=p5WO=Ol?r9-B{l$M#WMey3q5+S`yW=xS1+BD%dj1 zGDYV@BO@`5-u%cIDr0I_=>Ei#if+-Ycq_|dBTrZNBP~k=O#wn%q9zljau?Z36;%LM zY1(&gL&~>yv-E;XI{vv^p~-NUJC6($KM!=14VEEOlG;mA80Nk0aV$vCQf~k6M%U*=~yRS8z-x!8ovVm4PPYn;g?#= zV4`PoLJuu!ue0}YA_XznnyMxHM=!fwe6UNNI@q6%%__mG_ z-=S%l8v4;vw9S>EN#C(rFSRgUHzw**I;hkkg0;A&O7B5QV*DV=iMJJ7&7B@zYg++V zK=|z2#~va^HzW%L#l-injV7N}md+Tc+-4VmChEW*imWOvP09PdNw9B!3hrOkiK=k>lR1J|IWb}t zt(XIQdbJdl$|LDju2zm_GTI@WiBf}q^&D~-wqkN9f)vI2s%qd=R*zJQyjU4M^zz(B zT*?t^>~v@(B!W^sO+<^~C0dth$;O(TR{qCelzVoY`1qo^Cm=khVk};}3*IY~P z{6MKEu)Bx_T)_j+JlZ-%QDOOar;092wrMt#vd&PhO-X1~deu*)F1T|?Y@ez_s zy5*co;7!iAReO3Ch%NMds|)TmHlCt{QM5|ZSk6J`rFoW->0c&mU1h>v644~J7MG_O zqgS;Apsuc8#&DP=GD#f@L5sn7a z9BhP%Ae;E0t8HDpgzO{6e5jsl6;;39!oY`u%vH^1MT8ry+&!FUeUorz_AL%cC+CQ9 z)njI+sl;a^AXj=ezsu;FSk>XnG?jUe2RcGq`KQLu((IvDAF4hkN+3PNvvxXNkz1%_ zsfs>LOx!#u>&|-u`}EO`#;05ERkq!??L8t~U~&U{ zI!ieUxwmfwSfZ5NfZ$u0Kvgs1X;fZM=fb6|iJdI@PszbnRy>GMnutwnn8g2h{-_Jn;FSjkIebD;~!+iE#Qi zU$#@JiK}GWtdJJ^OjNi=)Z~vIIySLY&i+ozwdVOcXpbg?cD0oF%2TYI@{=2Z*lm9A z0H^hEEbh8c`AM9hA_UOf!yPVUVeGgnbCl1IJZ>RL)<9kR$Z&W^c?Gjpr9@-TvC=A8 z4Z>v6wuGPhJ7Prd`Lg0FWvX9W9C}z=KiL++z%oYFQd5MLGh&RIR<0_u<3dx46=~Z_ ztmue|!*&C=ewS)@B&nhicAB~6YnoBOn;&MVRg5mxvU$FB17MKJ&J!iGL6&yfdCWl$ zak_TWIbw{8?QWiC)H;h39_sK1G3I#Llt{hoBx(#WU{jgj24+;OO16NYGU*A%RRMlX zKZ&%&ri;&5xWn+?BzLBWGsJXifaE>T614sBV3F`!fkjF7(vq9b6LE7p6$+TG+Dska ztrk%k#ip}?CsfYyMn`c>Ok&fsxN9kD$Wh~sBv!ibaEACrr(!c)QI>e@+u;N`f~~65 zJ223C>Pkvb1^x4^tH|@Aa*{8s+m78TcPIxOCXU*bXi=59PiI?kdQ9+yU106wNZf97 zYzDYf!>Nhhm#s9ZA`_k&yn^tTIiEIjVP|krit%u;CDs`gOyi~df^SYgm*0vK-Z*0^ zc4K@MD4QVk7B69vXzQ1Q-O$Aw)dDjHCO1wag!gLcErY>c-0VVm1Xfn>1B#Y*&2>fJ zsBHg&yrW~`8_ukIh5kI|qHvIc)|mnuUaf7{s=|#_Q8nRP)oou0_$?|)g?C~_XSyR; zW^$&sYFTB*_zCvNLjNhuA^nzI{%OE2U0is?ZEK}mMWIbhN zzab#`4HMstW3)k50js#W=2=45s}+;M$Rg$Va%xpERs^DzIXJ}tL!79l6OyTd8xk~O zp4{kc-k>_bz9rha^&*-eTSKSg=~aE<$+70HC?$y&3-4(t*+8SYf;T$AuBUW*z_UhN zilrQr(2&3xV#-d7L2{teIv{d;hVAX{;GwaKIV3UY@1Q8r4x~n3l}AExVFWuMIJwoc z5VlhCS8V2FJjFIEHWPM~S!G8qD8)Q9HLGlQs*oO#t>~$SnV~W?a@pD};CUn`tbwz7 ziZloDtVE$+(NA5XGeMlAm8w>vBvREo9B%}yl5-WYnYb4;S}<4Uy<1^$$TSN_a%Zy0 z#9y2(Hq$TFut)3n3t4%%s!Fmhg({JNOypA`gL~tNJjI;QYRFU=Qm~poW6e&=_~OUF z3s_fw$0QrieS&_rXHzk?q!{x_UbK1;z5tV1$q5QX5Y@uCzknyRR_Yk>NV!a>?2O%F2S(Fy+5j+Vr=sh zF|Yit2BFjVt531f2Lsz&ST9O{h^u`E5T8y$0$V6KTgmzQASR%To_!2nBp4%d2M*^l zEH<*t!NJbXm~zntFBeN&=c&zo@FXbE2F0i)!w<}-oF^l&3GRcJyLMP8h-I=ROhd(; zJfDTr9#B7%4QQB89~n1hE)^#j5xo=t;8<|6FkyTy&1a6wTmZUaCHjU##4A4>x*RUX zM8}}{i$!!*WxQ+*uYv@RKn90%!VY6W#rXK0{1G!|DxQ^R1o&4_rrT6M2E#{}Wp67z z$kyig=Bm@~()?J#Xy;<`cw1JPAURQ6%mjz;1zY&-LcQ~Y03B6Edu7^aT_uUQ+J$6p zeCuho0zWMfsX;XJrCP>+zo2V%0o@sFk!0Ld+^NPS5l;4s$(8-lR~SU^z{ijHbV5yC zs%APw(As#o!LH37jrl^&WWUu*)$CJj^=q24wQ=HkGJYCvmwV4OnQQ!Hdm@`}UAum2 zQ_X1Aiq!Dc%C+&GhwQXV&5+$|hU^^QX?X3BVKqZ`88U=2)))_tNWPtGb{ZPrX_wle zyX-iG{#%=GR;X#xMzi@^0(m}3tWt44k!^pj7axg;y>oJsrKXv9PrlV?Pb!&dEfUL8 z)8snswefMZQj)A^B;r>)cyMQDXF|r}wYc-Rz~CIf;SbIY4uCK?t(6RJ$qyd5c73{- zchWWEh*$P&D!YjN{6V>8Jt6Sdm-ux78Y_IMR9X-c|k&5AuG)2YDSY@0NT@@*I7McaC|9x6Lggr~K&dab7PH=HYcx%tt<~ zw|QObr$jp${Pknw(#3f?=Y8e1&+u_xcJ*K@B$CX-5&8)yE{}kq5#d`hCEr%vKfqJH z<2>U3m^=oJRDZBHxIP@JLK-u#9DX)el#@f4 zxjfAnL4v1@7E?U!#O0nZM$T*|vtlXl`7~pEb}`$`Y`#1mvtlWiNK#=6s8!ll2-5VM z%@1xGxf1c|ZjpEqcRnv^b~DY#)6}|cyvnguZqAxfGOtebwd?`nZ~o3N<5w!qMr5V~ z11m&y^WyIuy!8u;wi76odGa@W@mGkC5S&yoU{xzcs`>0c|J~n~*eL2UGg&{_)4xs3 zGCNi)RiFJu9%39x$SHQXPLWoXP|I)l2(Z?}>tn^z^opfyZE)opE>od-6&Uy((Xza9 z_$78v6hEuH4;OOOOd#FHls3qtoU^BBwo)D z)R$ke{Gz`8@{5+=OmmGTDp017y1+}%s!f)cNv1t*rC%4GJLn6<4 zri!>buDh3w%U&xUiw20lNlB%SIR5ael`360-*n%R(lUNa)u0mXC7yOb%9PYo5ioAk1Gk$Y}S zSg&y22no8azvA=AJx{f$&s&T60DYrW91Ll=2lNOeZ0y%&xXjo4^4%ZsN#$Y(ZItG}(R8i)U=mzDWuX}#)L7%+KZ*%d4oa>ci6#d$&V#k_iZ zcOp{C1%>q5MMSe!=<pw~UrZIK6NkLgTA;n_AAdPd)(EwqT z9dn_!D@_V%VQByNU!k53`v!bS9M9)R zZNKST)PWvXolo3+6{$%TQMIgx`oHr)^-2w|ng);91u9z8!CXTJ0azACRd#8wm3+gx zr&^;Ds-^kkCMp(IUJ+f=cSr+aOG;IMf*ZGmjZ!wMVmo=->3Cnwm#;uecjmJ*jmnYS zcw@HMMjLje+Vu7T&({j0a=zW867YWe$FwVhqD1s6V=BM@N47m3a!ExMqAk!GbYtQ| zEaLy#liMqn1`@7eWV(NJTZ~CT5C3nyxsB(DXhMj-W}r`I^Cxkp#3T^}nzI#N;8s0Y zN|b8El(yzQVNDsYjqz=zpXRpjXl8Xj!JNtzez@nk8)!M8Myok6?WS^BpT@v4h(8Jz zD=ai&P(%X~hw(j?O%{bqfJWtef6BYj5Yqp?=Kb$_&3kmne=x4FV|AKY?y~p1>-d~I zKQIkJoXyn^i{d%QaA~=M`^w>0?G+KLz~My&E#o5)NLzi&U;K`iAdnnbS6}k%H}i>Q zXbaYr2I7kI?}tY!vK zr88AFL6?_^k5-MeVn*J@H{~vm>+;X6kV=wYKXT?P&UZD($7&`l!SJB6)>O`E=#CPof zkvGx}n>(KN_y0bS{;h9Y{_g|n|9v1md?1|-N5*eL)b5eH{Kaq`VGi>O5{fBx-eYB+qpnW@=XUcJZO6r00t@fkYhs znTSs_zDC7NAkXOQ>^XSM_>pJX6Be4t;gHDskX;g+y&mMGvkwVnDod~?xO?sr{Z2ZC}-qCb-mJT z{57^+I5#;2^lyFQeRMXHA@ZIrdF8#)g`*fH%DHoWYcjA!8$T4^XnuOi!B?=0+>Hw5 zNnm(@g?E+>lMDmWA@sW$fd9q!2QjhwMQStlqX}i zCszHhzrjoQQX9X}Etk2AGLi4t`Cgv8pNX#OTAmea@Q6l}XjM8VQzE3K$LH!D>u6?c z-b?u_`B;6G>UgVD3tr#{(`|)Wrr~n6MswQ7>;Vsji z^@K||>~`QkeTX2x?N?Cgqt}tK5(wj z1&U~v%%)i%uMVoV_Bed-zCnGDL-HM_h1Ub}O|N;kB2@=O*f7@>9(gt@T@lxqdZlo5 zP27L8uy&(##?GYPT?y&}-;E@eoO+iKJUDM0I$T*lsiQ4Lu}53}Sh4Z!L!-wO?Jc^V z7+St_GITf;$xJ-#J?;W6S7r?>Bu92Ly=4~fPMf<<>*_mpVX>nwH+{EY$Bg8RuplN$ zuR9asf(#xm!B2T9eJ@5YuZiBhNRSfCy9R7M$3=hx^`?sf`~cGILUuMsQ)Dwq_^kC~ zZB1a15Xqw+&KmXVVJ;zCL4y6aKJUrvCiNmA#Uj3o_D9Kk@!{*+l^=dL2hMCOk?1>c z!JWCm4`v&SIhbTIQo?hwJCOMK=;3ju-bLL)nc8rS<-Qx7!#55~Nj@LYoP}V_K7dMk za%Q~pQn72yj=mLR9_{5Qan`Y&IIZ7)&`u>`8uD z3k`)eWCeNBGQ*GR<=v>C$xz$FgdbBi_a9YpFNpR+4=N>{bdr^zMuSBXq+8Noc`66G zVqArWewXF3UW8Iz4{p~8VdPirO6ZOojfE^dsdOGOajb4O7s>>_<8pYgp6~Y*{>2b` zqft^tbIwW5W$wg$8^sXe8IgxPvl@BgtJ#>yH?r`>N2Ry4MB@x*HaMN;XpXfRH3SHq z3n_^m8{mIz5^tRiaG4e9MR(2Mafw<%xE6Lnik{I99RsbT@W@r#rW^LT`WX6b>*0rH*A2YX*m^5xy)tbuEXun)_l5e)7&H^r+e+B-OK2cv`;tgCwPyq7&3*9w)J4b4n$>^EwqQaw_>!ow%(_7VW2Z@ukb& z?m>k|T*^|zXIsjWsyuXW?&h(cw#RDh?os;+!!J#(5L5bwiA4qswU^VNVYGeKUEqPt z^14;G{k|BkwraOQTSj2)IvwME%oleAMa*IIG%D+!L?z00g9=kuY4KLvAu5zDhHq7M z-@~4~7^-YFVUy9@>N=9vJ1D+M_MN(d5EKFg}gsgYf!999Ab7o3ZER34!h zGTNGm_ctC@wSxyQ;HDPtZQOGP%hUD?`}4VPbA?NXllN=CyZ6?=*>y|CML&!us4$fV zuHS!lXP>&8UA%?FjbDY1cq@d&uZm*{%D4)y3D zAt=r)$~C)_z`2_=;RH*+!;>%pYujj!Jx2W-nuq|qp){_w1lg%qnWRwVMiJfZXOoK?Pg*P&W zB2|LqV;ADOxUUClZz3xl*)D0Fs)(F5mKf+G<@GCbla<7myb*&3UnE6b7_?ZHqGXN8 zMw3apwJ`B><;+9qeSvcQb@={QxPTgsQxRtu1y|{<1hj&Er^u*k>qR6bA|R z7%F@6!0c$2XP3{)*Wh$tpxG}G=2}-Q&G3a{X?c!4Ul^qG?WCjHd3%D*DRXn?3NO2l z3Li1Sx4f^ZZ_SHGH2in;q4{#39Epx7_N3XqT7^EN9y#b`>x7co_GT}`iqO7(&7P)| zp4BwJ^TF>zcx*JNl687@W1`>esxKufdP-JJq4~@r6>pR9B?`hO1P{@hm#laWqdB9` z+EvOZSL?BoDf$^slc;aQ#Il>iE9LYu^4LajiIhaP^J{>%@z0t7*4l`3rOow1&#VXf zZ1TvpMX$x|p(5n%uA;$a9eB(r#54MAN@P{=4#PYSN>x%gR!CA0o;IPC$w0lun(DCE zY}8`Yihc2*UX>)r8rffmYbZA$#%IrNtd{0;V!UQg3dTl}y^7Onqj^rmH|O!nV!}*L zysg-(DA11A(!^BEPgb#qmeIJ$T0=2$#clKC-rE2tGl9i6T*qZr+m>vWA6&5&V;wO0iLj(n%Qh zd}Ii%p35()mCMlFSfhQSbdtlG7W-PPl7pqZMr{>C`6+I@zIe8oT_jw-_s+V}O>ES- ziH+u*0ih~+Tr(HBTB+0nfaz0gR6fs)ejYdNm5#l!(3R%LWC)A1twi=|asqQ~t!$Yd z`_478NufC__o(yDT;V0;V!5c4EZT2ZZzSULYr$p65v7!@U#_CUZIR}J0tR)Nz+&Wb zy|_l)Ng~RwiZz1&sFtF-mF}7|CYx^BGKXGpG!)N`bdy7FIH;H$3R=aa_3UKyove^j zTgG_vR)VOuML_Fxaxs02r-^n6c%av1TC)6*0{=5_D$t*Nt81>A2@lm7GpcC9okAh+ z@k6EJBgzDB^c359!OyXmY>T&Ishk;)2l+!II3tQEL`qfX{62T-WsEQ{sY#5OttPpk zGFL2=JVV~*2EvP+1{u&y#BE^U<*Dz^i%UC}PfL7A&Cs3M&6?jgk=*%#tg8`;hMyG_ z&zzi`PhfWgH_slx1<>~ZOW4cEVKEnuiNOJ1UURr`jD>o=E{|$q7azG8z(zG~s;Dp| z4va575KnD$xka@0;OMZPj@LdLy^mbQ8TBo~s|taCmHHc0$Wrc7R+pA+{Je%!>I_!m z3-s->=0fUK@pc5hbu;UW^{z=yXFB4lp*J~nxrKzj08+U^xhkZjsPGwHx13bekH%}JStC5{4U~VpOEEBYT;0^5AMz$@+(kD5>R)3y;aNx)S)Ok8U()SL8ho`6WK8Jc#*pLrLvrg8{N}g z=m|1cp>AY`s}O5qe}&jYw_uJX=()52t%8#`>5}}MeL?R=bmTS#BDW1iaEc+wpvV<8FD<`bw z`n=#6(cZ)u*)A2*MOv9m=5%Lvq0Ney`6idY#$pi_VkJa^m4n=TpOZOl?ML2&lOzj@ zu6=t%_}ESb^Kqp_V>q_bDp{SvWYL|4pZYuEDbn+U7FEhrf7&8E<6-?|qa)9?8urU9 zk5aShIP zBp z$k_DY>3X4(@}Bv0x&4Oyt6hC?tjx<0iIuK}Ze%$}*ss_OVYpqdLtd{lnZoyjOB{y- zO}no51Xa+V`C#HIy5cO5T2Fw4m-eV#LoLjSxVkUnFm{RNUTtIPY%9(e3vwk3_KM8r zx!q>og9Y6vmTyC%HHTRw8qW26I*>Hx6@!w_)l< z%7H?o*@fy6zU6xTUbM7pE(lz?vbf&SHBT)tIgmR9MzM&fH0 z(?&+mP1vvL*msV6gXaDNdKTXF{KGY9U#!V@>)D5+;vHEpuP3Yd$c{{ODx2xAGMUXA z*b5uGp)qy@uY#{cgW&e9_w@pX%G^W9U4TF+n|L0Y@2qwI_aGw=0~Ngj8kQTS;kE3E z?z-Sd)tj{2hHTYzJo3gJHN-kH0hVm9T%KG~g>$f?7D!r9wky(8zowkIY|OO*-E%Qo z`+D(U<+>ewA{du`A+w0v z?7|dr2rOx!C+4Pli@3ouDbMza%)?A>c;S4+Q(2HCFWXB<{LMzgF4sYFpthaHUPx|6 zslD+63VZ``4m)zlNYE+tFP6hbX0(xvPUzJhxEHaqwVMM>mFgDwnuoy-2+j}ptQuG; ztw3z%WV~NJD>joLD-U7Js_1=`ayf_MT(wM$q9xgw*~y1D8-y-nGsE|JqqoM+3gkUI ztLXV=^%xtu<4bN7v$K^j%`?@FV3uuKnCXN%xYG8jB$zw2xhA6tC^;x6;FVj*O6z36 ziHo|NYZ0Yzc&?=)EKp*W7D0^PCNb>iGSe@LI>}ru5N$9cHl~8yZ&BJ6Yk78`R0>Ds zG$U{-}PVV5vm147S{4pCGovt#-+r#Y}M7rX4Z#So6m|7d&K|TR$;2~WL0>T zcpzU-vQ8b^FS8C1KNMREf*3|iKc@Ue%*f%DU%d;j!gTD%*J7?*F`3fPkC}tjdaMlJ zOnv2|4-?_$Lv#)=Uku*EHD}Vo7*pJe3M$~ZG>?D}^mZVe3#}s2UG}(}N!Z2;Tyf`O z(Bq~-RqZlL)2^ha55-j|F1GTR$0{`Z)hDy*gXc=$&w=?4UITpxkbF1L=YyhdkHF<1Z; z_;7Hhj6g4=*B;0ZIf+Q!E0GkG>$0zlBDN?iC(4!a%4Fl=GcqtJNq@~7Jp{{avE;;W z@E`>(Gm>$eQ^bZ0O%7b7&}EtCORu`(*Vy#x$nMhoSiz{hWAe^+ zR{2l4v7(s4s!_U7`Oy|;>iiX#i79@iEJNytJ0CAC*wd%CcU#Y>^CXul`v3iE7OM;B l&S3k!R9mUisTTr@NV^vk_go$~, 2011 msgid "" msgstr "" -"Project-Id-Version: RhodeCode\n" -"Report-Msgid-Bugs-To: marcin@maq.io\n" -"POT-Creation-Date: 2013-06-05 19:55+0200\n" -"PO-Revision-Date: 2013-06-02 13:31+0000\n" +"Project-Id-Version: Kallithea\n" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" +"PO-Revision-Date: 2014-02-13 14:34+0000\n" "Last-Translator: marcinkuzminski \n" -"Language-Team: French (http://www.transifex.com/projects/p/RhodeCode/language/fr/)\n" +"Language-Team: French " +"(http://www.transifex.com/projects/p/Kallithea/language/fr/)\n" +"Plural-Forms: nplurals=2; plural=(n > 1)\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -"Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: rhodecode/controllers/changelog.py:149 + +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 +msgid "There are no changesets yet" +msgstr "Il n’y a aucun changement pour le moment" + +#: kallithea/controllers/changelog.py:186 msgid "All Branches" msgstr "Toutes les branches" -#: rhodecode/controllers/changeset.py:84 +#: kallithea/controllers/changelog.py:189 +msgid "(closed)" +msgstr "" + +#: kallithea/controllers/changeset.py:87 msgid "Show white space" msgstr "Afficher les espaces et tabulations" -#: rhodecode/controllers/changeset.py:91 rhodecode/controllers/changeset.py:98 +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 msgid "Ignore white space" msgstr "Ignorer les espaces et tabulations" -#: rhodecode/controllers/changeset.py:164 -#, python-format -msgid "%s line context" -msgstr "Afficher %s lignes de contexte" - -#: rhodecode/controllers/changeset.py:345 -#: rhodecode/controllers/pullrequests.py:478 +#: kallithea/controllers/changeset.py:167 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 #, python-format msgid "Status change -> %s" msgstr "Changement de statut -> %s" -#: rhodecode/controllers/changeset.py:376 +#: kallithea/controllers/changeset.py:386 msgid "" -"Changing status on a changeset associated with a closed pull request is not " -"allowed" -msgstr "" - -#: rhodecode/controllers/compare.py:74 -#: rhodecode/controllers/pullrequests.py:256 -msgid "There are no changesets yet" -msgstr "Il n’y a aucun changement pour le moment" - -#: rhodecode/controllers/error.py:69 +"Changing status on a changeset associated with a closed pull request is " +"not allowed" +msgstr "" + +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +msgid "Select changeset" +msgstr "" + +#: kallithea/controllers/error.py:72 msgid "Home page" msgstr "Accueil" -#: rhodecode/controllers/error.py:98 -msgid "" -"The request could not be understood by the server due to malformed syntax." -msgstr "Le serveur n’a pas pu interpréter la requête à cause d’une erreur de syntaxe" - -#: rhodecode/controllers/error.py:101 +#: kallithea/controllers/error.py:101 +msgid "The request could not be understood by the server due to malformed syntax." +msgstr "" +"Le serveur n’a pas pu interpréter la requête à cause d’une erreur de " +"syntaxe" + +#: kallithea/controllers/error.py:104 msgid "Unauthorized access to resource" msgstr "Accès interdit à cet ressource" -#: rhodecode/controllers/error.py:103 +#: kallithea/controllers/error.py:106 msgid "You don't have permission to view this page" msgstr "Vous n’avez pas la permission de voir cette page" -#: rhodecode/controllers/error.py:105 +#: kallithea/controllers/error.py:108 msgid "The resource could not be found" msgstr "Ressource introuvable" -#: rhodecode/controllers/error.py:107 +#: kallithea/controllers/error.py:110 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." -msgstr "La requête n’a pu être traitée en raison d’une erreur survenue sur le serveur." - -#: rhodecode/controllers/feed.py:52 +msgstr "" +"La requête n’a pu être traitée en raison d’une erreur survenue sur le " +"serveur." + +#: kallithea/controllers/feed.py:55 #, python-format msgid "Changes on %s repository" msgstr "Changements sur le dépôt %s" -#: rhodecode/controllers/feed.py:53 +#: kallithea/controllers/feed.py:56 #, python-format msgid "%s %s feed" msgstr "Flux %s de %s" -#: rhodecode/controllers/feed.py:86 -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Changeset was too big and was cut off..." msgstr "Cet ensemble de changements était trop important et a été découpé…" -#: rhodecode/controllers/feed.py:90 +#: kallithea/controllers/feed.py:93 #, python-format msgid "%s committed on %s" msgstr "%s a commité, le %s" -#: rhodecode/controllers/files.py:89 +#: kallithea/controllers/files.py:92 msgid "Click here to add new file" msgstr "Ajouter un nouveau fichier" -#: rhodecode/controllers/files.py:90 -#, python-format -msgid "There are no files yet %s" -msgstr "Il n’y a pas encore de fichiers %s" - -#: rhodecode/controllers/files.py:271 rhodecode/controllers/files.py:339 +#: kallithea/controllers/files.py:93 +#, python-format +msgid "There are no files yet. %s" +msgstr "" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 #, python-format msgid "This repository is has been locked by %s on %s" msgstr "Ce dépôt a été verrouillé par %s sur %s." -#: rhodecode/controllers/files.py:283 +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:346 +#, python-format +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "Une erreur est survenue durant le commit" + +#: kallithea/controllers/files.py:373 msgid "You can only edit files with revision being a valid branch " msgstr "" -#: rhodecode/controllers/files.py:297 -#, python-format -msgid "Edited file %s via RhodeCode" -msgstr "%s édité via RhodeCode" - -#: rhodecode/controllers/files.py:313 +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "%s édité via Kallithea" + +#: kallithea/controllers/files.py:403 msgid "No changes" msgstr "Aucun changement" -#: rhodecode/controllers/files.py:322 rhodecode/controllers/files.py:394 +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 #, python-format msgid "Successfully committed to %s" msgstr "Commit réalisé avec succès sur %s" -#: rhodecode/controllers/files.py:327 rhodecode/controllers/files.py:405 -msgid "Error occurred during commit" -msgstr "Une erreur est survenue durant le commit" - -#: rhodecode/controllers/files.py:351 -msgid "Added file via RhodeCode" -msgstr "%s ajouté par RhodeCode" - -#: rhodecode/controllers/files.py:368 +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "%s ajouté par Kallithea" + +#: kallithea/controllers/files.py:461 msgid "No content" msgstr "Aucun contenu" -#: rhodecode/controllers/files.py:372 +#: kallithea/controllers/files.py:465 msgid "No filename" msgstr "Aucun nom de fichier" -#: rhodecode/controllers/files.py:397 +#: kallithea/controllers/files.py:490 msgid "Location must be relative path and must not contain .. in path" msgstr "" -#: rhodecode/controllers/files.py:431 +#: kallithea/controllers/files.py:524 msgid "Downloads disabled" msgstr "Les téléchargements sont désactivés" -#: rhodecode/controllers/files.py:442 +#: kallithea/controllers/files.py:535 #, python-format msgid "Unknown revision %s" msgstr "Révision %s inconnue." -#: rhodecode/controllers/files.py:444 +#: kallithea/controllers/files.py:537 msgid "Empty repository" msgstr "Dépôt vide." -#: rhodecode/controllers/files.py:446 +#: kallithea/controllers/files.py:539 msgid "Unknown archive type" msgstr "Type d’archive inconnu" -#: rhodecode/controllers/files.py:631 -#: rhodecode/templates/changeset/changeset_range.html:9 -#: rhodecode/templates/email_templates/pull_request.html:12 -#: rhodecode/templates/pullrequests/pullrequest.html:124 +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 msgid "Changesets" msgstr "Changesets" -#: rhodecode/controllers/files.py:632 -#: rhodecode/controllers/pullrequests.py:149 -#: rhodecode/controllers/summary.py:76 rhodecode/model/scm.py:682 -#: rhodecode/templates/switch_to_list.html:3 -#: rhodecode/templates/branches/branches.html:10 +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 msgid "Branches" msgstr "Branches" -#: rhodecode/controllers/files.py:633 -#: rhodecode/controllers/pullrequests.py:150 -#: rhodecode/controllers/summary.py:77 rhodecode/model/scm.py:693 -#: rhodecode/templates/switch_to_list.html:15 -#: rhodecode/templates/tags/tags.html:10 +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 msgid "Tags" msgstr "Tags" -#: rhodecode/controllers/forks.py:176 -#, python-format -msgid "Forked repository %s as %s" -msgstr "dépôt %s forké en tant que %s" - -#: rhodecode/controllers/forks.py:190 +#: kallithea/controllers/forks.py:191 #, python-format msgid "An error occurred during repository forking %s" msgstr "Une erreur est survenue durant le fork du dépôt %s." -#: rhodecode/controllers/journal.py:110 rhodecode/controllers/journal.py:153 +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "Dépôts" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 msgid "public journal" msgstr "Journal public" -#: rhodecode/controllers/journal.py:114 rhodecode/controllers/journal.py:157 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 msgid "journal" msgstr "Journal" -#: rhodecode/controllers/login.py:138 -msgid "You have successfully registered into RhodeCode" -msgstr "Vous vous êtes inscrits avec succès à RhodeCode" - -#: rhodecode/controllers/login.py:159 +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" +msgstr "Vous vous êtes inscrits avec succès à Kallithea" + +#: kallithea/controllers/login.py:237 msgid "Your password reset link was sent" msgstr "Un lien de rénitialisation de votre mot de passe vous a été envoyé." -#: rhodecode/controllers/login.py:179 +#: kallithea/controllers/login.py:257 msgid "" -"Your password reset was successful, new password has been sent to your email" -msgstr "Votre mot de passe a été réinitialisé. Votre nouveau mot de passe vous a été envoyé par e-mail." - -#: rhodecode/controllers/pullrequests.py:136 -#: rhodecode/templates/changeset/changeset.html:10 -#: rhodecode/templates/email_templates/changeset_comment.html:8 +"Your password reset was successful, new password has been sent to your " +"email" +msgstr "" +"Votre mot de passe a été réinitialisé. Votre nouveau mot de passe vous a " +"été envoyé par e-mail." + +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 msgid "Changeset" msgstr "Changements" -#: rhodecode/controllers/pullrequests.py:146 +#: kallithea/controllers/pullrequests.py:157 msgid "Special" msgstr "" -#: rhodecode/controllers/pullrequests.py:147 +#: kallithea/controllers/pullrequests.py:158 msgid "Peer branches" msgstr "" -#: rhodecode/controllers/pullrequests.py:148 rhodecode/model/scm.py:688 -#: rhodecode/templates/switch_to_list.html:28 -#: rhodecode/templates/bookmarks/bookmarks.html:10 +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 msgid "Bookmarks" msgstr "Signets" -#: rhodecode/controllers/pullrequests.py:321 +#: kallithea/controllers/pullrequests.py:330 msgid "Pull request requires a title with min. 3 chars" msgstr "Les requêtes de pull nécessitent un titre d’au moins 3 caractères." -#: rhodecode/controllers/pullrequests.py:323 -msgid "Error creating pull request" -msgstr "Une erreur est survenue lors de la création de la requête de pull." - -#: rhodecode/controllers/pullrequests.py:343 +#: kallithea/controllers/pullrequests.py:332 +#, python-format +msgid "Error creating pull request: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:354 msgid "Successfully opened new pull request" msgstr "La requête de pull a été ouverte avec succès." -#: rhodecode/controllers/pullrequests.py:346 +#: kallithea/controllers/pullrequests.py:357 msgid "Error occurred during sending pull request" msgstr "Une erreur est survenue durant l’envoi de la requête de pull." -#: rhodecode/controllers/pullrequests.py:385 +#: kallithea/controllers/pullrequests.py:397 msgid "Successfully deleted pull request" msgstr "La requête de pull a été supprimée avec succès." -#: rhodecode/controllers/pullrequests.py:481 +#: kallithea/controllers/pullrequests.py:485 msgid "Closing with" msgstr "" -#: rhodecode/controllers/pullrequests.py:518 -msgid "" -"Closing pull request on other statuses than rejected or approved forbidden" -msgstr "" - -#: rhodecode/controllers/search.py:132 +#: kallithea/controllers/pullrequests.py:522 +msgid "Closing pull request on other statuses than rejected or approved forbidden" +msgstr "" + +#: kallithea/controllers/search.py:135 msgid "Invalid search query. Try quoting it." msgstr "Requête invalide. Essayer de la mettre entre guillemets." -#: rhodecode/controllers/search.py:137 +#: kallithea/controllers/search.py:140 msgid "There is no index to search in. Please run whoosh indexer" -msgstr "L’index de recherche n’est pas présent. Veuillez exécuter l’indexeur de code Whoosh." - -#: rhodecode/controllers/search.py:141 +msgstr "" +"L’index de recherche n’est pas présent. Veuillez exécuter l’indexeur de " +"code Whoosh." + +#: kallithea/controllers/search.py:144 msgid "An error occurred during this search operation" msgstr "Une erreur est survenue durant l’opération de recherche." -#: rhodecode/controllers/summary.py:182 +#: kallithea/controllers/summary.py:203 msgid "No data loaded yet" msgstr "Aucune donnée actuellement disponible." -#: rhodecode/controllers/summary.py:188 -#: rhodecode/templates/summary/summary.html:149 +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 msgid "Statistics are disabled for this repository" msgstr "La mise à jour des statistiques est désactivée pour ce dépôt." -#: rhodecode/controllers/admin/defaults.py:96 +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:97 msgid "Default settings updated successfully" msgstr "" -#: rhodecode/controllers/admin/defaults.py:110 +#: kallithea/controllers/admin/defaults.py:111 msgid "Error occurred during update of defaults" msgstr "" -#: rhodecode/controllers/admin/gists.py:56 +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 msgid "forever" msgstr "" -#: rhodecode/controllers/admin/gists.py:57 +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 msgid "5 minutes" msgstr "5 minute" -#: rhodecode/controllers/admin/gists.py:58 +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 msgid "1 hour" msgstr "1 heure" -#: rhodecode/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 msgid "1 day" msgstr "1 jour" -#: rhodecode/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 msgid "1 month" msgstr "1 mois" -#: rhodecode/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 msgid "Lifetime" msgstr "" -#: rhodecode/controllers/admin/gists.py:127 +#: kallithea/controllers/admin/gists.py:147 msgid "Error occurred during gist creation" msgstr "" -#: rhodecode/controllers/admin/gists.py:165 +#: kallithea/controllers/admin/gists.py:185 #, python-format msgid "Deleted gist %s" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:50 -msgid "BASE" -msgstr "Base" - -#: rhodecode/controllers/admin/ldap_settings.py:51 -msgid "ONELEVEL" -msgstr "Un niveau" - -#: rhodecode/controllers/admin/ldap_settings.py:52 -msgid "SUBTREE" -msgstr "Sous-arbre" - -#: rhodecode/controllers/admin/ldap_settings.py:56 -msgid "NEVER" -msgstr "NEVER" - -#: rhodecode/controllers/admin/ldap_settings.py:57 -msgid "ALLOW" -msgstr "Autoriser" - -#: rhodecode/controllers/admin/ldap_settings.py:58 -msgid "TRY" -msgstr "TRY" - -#: rhodecode/controllers/admin/ldap_settings.py:59 -msgid "DEMAND" -msgstr "DEMAND" - -#: rhodecode/controllers/admin/ldap_settings.py:60 -msgid "HARD" -msgstr "HARD" - -#: rhodecode/controllers/admin/ldap_settings.py:64 -msgid "No encryption" -msgstr "Pas de chiffrement" - -#: rhodecode/controllers/admin/ldap_settings.py:65 -msgid "LDAPS connection" -msgstr "Connection LDAPS" - -#: rhodecode/controllers/admin/ldap_settings.py:66 -msgid "START_TLS on LDAP connection" -msgstr "START_TLS à la connexion" - -#: rhodecode/controllers/admin/ldap_settings.py:124 -msgid "LDAP settings updated successfully" -msgstr "Mise à jour réussie des réglages LDAP" - -#: rhodecode/controllers/admin/ldap_settings.py:128 -msgid "Unable to activate ldap. The \"python-ldap\" library is missing." -msgstr "Impossible d’activer LDAP. La bibliothèque « python-ldap » est manquante." - -#: rhodecode/controllers/admin/ldap_settings.py:145 -msgid "Error occurred during update of ldap settings" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:58 -#: rhodecode/controllers/admin/permissions.py:62 -#: rhodecode/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "" +"Vous ne pouvez pas éditer cet utilisateur ; il est nécessaire pour le bon" +" fonctionnement de l’application." + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "Votre compte a été mis à jour avec succès" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "L’e-mail « %s » a été ajouté à l’utilisateur." + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "Une erreur est survenue durant l’enregistrement de l’e-mail." + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "L’e-mail a été enlevé de l’utilisateur." + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 msgid "None" msgstr "Aucun" -#: rhodecode/controllers/admin/permissions.py:59 -#: rhodecode/controllers/admin/permissions.py:63 -#: rhodecode/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 msgid "Read" msgstr "Lire" -#: rhodecode/controllers/admin/permissions.py:60 -#: rhodecode/controllers/admin/permissions.py:64 -#: rhodecode/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 msgid "Write" msgstr "Écrire" -#: rhodecode/controllers/admin/permissions.py:61 -#: rhodecode/controllers/admin/permissions.py:65 -#: rhodecode/controllers/admin/permissions.py:69 -#: rhodecode/templates/admin/defaults/defaults.html:9 -#: rhodecode/templates/admin/ldap/ldap.html:9 -#: rhodecode/templates/admin/permissions/permissions.html:9 -#: rhodecode/templates/admin/repos/repo_add.html:10 -#: rhodecode/templates/admin/repos/repo_add.html:14 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:13 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:9 -#: rhodecode/templates/admin/users/user_add.html:8 -#: rhodecode/templates/admin/users/user_edit.html:9 -#: rhodecode/templates/admin/users/user_edit.html:133 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/admin/users/users.html:85 -#: rhodecode/templates/admin/users_groups/users_group_add.html:8 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 -#: rhodecode/templates/admin/users_groups/users_groups.html:9 -#: rhodecode/templates/base/base.html:317 -#: rhodecode/templates/base/base.html:318 -#: rhodecode/templates/base/base.html:324 -#: rhodecode/templates/base/base.html:325 +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 msgid "Admin" msgstr "Administration" -#: rhodecode/controllers/admin/permissions.py:72 -#: rhodecode/controllers/admin/permissions.py:83 -#: rhodecode/controllers/admin/permissions.py:86 -#: rhodecode/controllers/admin/permissions.py:89 -#: rhodecode/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 msgid "Disabled" msgstr "Interdite" -#: rhodecode/controllers/admin/permissions.py:74 +#: kallithea/controllers/admin/permissions.py:78 msgid "Allowed with manual account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:80 msgid "Allowed with automatic account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:79 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1439 rhodecode/model/db.py:1444 +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 msgid "Manual activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:80 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1440 rhodecode/model/db.py:1445 +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 msgid "Automatic activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:84 -#: rhodecode/controllers/admin/permissions.py:87 -#: rhodecode/controllers/admin/permissions.py:90 -#: rhodecode/controllers/admin/permissions.py:93 +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 msgid "Enabled" msgstr "Autorisée" -#: rhodecode/controllers/admin/permissions.py:138 -msgid "Default permissions updated successfully" -msgstr "Permissions par défaut mises à jour avec succès" - -#: rhodecode/controllers/admin/permissions.py:152 +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:139 msgid "Error occurred during update of permissions" msgstr "" -#: rhodecode/controllers/admin/repos.py:128 -msgid "--REMOVE FORK--" -msgstr "[Pas un fork]" - -#: rhodecode/controllers/admin/repos.py:168 +#: kallithea/controllers/admin/repo_groups.py:186 +#, python-format +msgid "Created repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:198 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:256 +#, python-format +msgid "Updated repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:271 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:289 +#, python-format +msgid "This group contains %s repositores and cannot be deleted" +msgstr "Ce groupe contient %s dépôts et ne peut être supprimé." + +#: kallithea/controllers/admin/repo_groups.py:296 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:302 +#, python-format +msgid "Removed repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:237 #, python-format msgid "Created repository %s from %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:174 +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "dépôt %s forké en tant que %s" + +#: kallithea/controllers/admin/repos.py:249 #, python-format msgid "Created repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:197 -#, python-format -msgid "Error creating repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:270 +#: kallithea/controllers/admin/repos.py:289 #, python-format msgid "Repository %s updated successfully" msgstr "Dépôt %s mis à jour avec succès." -#: rhodecode/controllers/admin/repos.py:288 +#: kallithea/controllers/admin/repos.py:307 #, python-format msgid "Error occurred during update of repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:315 +#: kallithea/controllers/admin/repos.py:334 #, python-format msgid "Detached %s forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:318 +#: kallithea/controllers/admin/repos.py:337 #, python-format msgid "Deleted %s forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:323 +#: kallithea/controllers/admin/repos.py:342 #, python-format msgid "Deleted repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:326 +#: kallithea/controllers/admin/repos.py:345 #, python-format msgid "Cannot delete %s it still contains attached forks" msgstr "Impossible de supprimer le dépôt %s : Des forks y sont attachés." -#: rhodecode/controllers/admin/repos.py:331 +#: kallithea/controllers/admin/repos.py:350 #, python-format msgid "An error occurred during deletion of %s" msgstr "Erreur pendant la suppression de %s" -#: rhodecode/controllers/admin/repos.py:345 +#: kallithea/controllers/admin/repos.py:402 msgid "Repository permissions updated" msgstr "" -#: rhodecode/controllers/admin/repos.py:375 -#: rhodecode/controllers/admin/repos_groups.py:332 -#: rhodecode/controllers/admin/users_groups.py:312 -msgid "An error occurred during revoking of permission" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:392 -msgid "An error occurred during deletion of repository stats" -msgstr "Une erreur est survenue durant la suppression des statistiques du dépôt." - -#: rhodecode/controllers/admin/repos.py:409 -msgid "An error occurred during cache invalidation" -msgstr "Une erreur est survenue durant l’invalidation du cache." - -#: rhodecode/controllers/admin/repos.py:429 -#: rhodecode/controllers/admin/repos.py:456 -msgid "An error occurred during unlocking" -msgstr "Une erreur est survenue durant le déverrouillage." - -#: rhodecode/controllers/admin/repos.py:447 -msgid "Unlocked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:450 -msgid "Locked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:452 -#, python-format -msgid "Repository has been %s" -msgstr "Le dépôt a été %s." - -#: rhodecode/controllers/admin/repos.py:476 +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "" + +#: kallithea/controllers/admin/repos.py:522 msgid "Updated repository visibility in public journal" msgstr "La visibilité du dépôt dans le journal public a été mise à jour." -#: rhodecode/controllers/admin/repos.py:480 +#: kallithea/controllers/admin/repos.py:526 msgid "An error occurred during setting this repository in public journal" -msgstr "Une erreur est survenue durant la configuration du journal public pour ce dépôt." - -#: rhodecode/controllers/admin/repos.py:485 rhodecode/model/validators.py:302 +msgstr "" +"Une erreur est survenue durant la configuration du journal public pour ce" +" dépôt." + +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 msgid "Token mismatch" msgstr "Jeton d’authentification incorrect." -#: rhodecode/controllers/admin/repos.py:498 -msgid "Pulled from remote location" -msgstr "Les changements distants ont été récupérés." - -#: rhodecode/controllers/admin/repos.py:501 -msgid "An error occurred during pull from remote location" -msgstr "Une erreur est survenue durant le pull depuis la source distante." - -#: rhodecode/controllers/admin/repos.py:517 +#: kallithea/controllers/admin/repos.py:546 msgid "Nothing" msgstr "[Aucun dépôt]" -#: rhodecode/controllers/admin/repos.py:519 +#: kallithea/controllers/admin/repos.py:548 #, python-format msgid "Marked repo %s as fork of %s" msgstr "Le dépôt %s a été marké comme fork de %s" -#: rhodecode/controllers/admin/repos.py:523 +#: kallithea/controllers/admin/repos.py:555 msgid "An error occurred during this operation" msgstr "Une erreur est survenue durant cette opération." -#: rhodecode/controllers/admin/repos.py:562 -msgid "An error occurred during creation of field" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:576 -msgid "An error occurred during removal of field" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:147 -#, python-format -msgid "Created repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:159 -#, python-format -msgid "Error occurred during creation of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:217 -#, python-format -msgid "Updated repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:232 -#, python-format -msgid "Error occurred during update of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:250 -#, python-format -msgid "This group contains %s repositores and cannot be deleted" -msgstr "Ce groupe contient %s dépôts et ne peut être supprimé." - -#: rhodecode/controllers/admin/repos_groups.py:257 -#, python-format -msgid "This group contains %s subgroups and cannot be deleted" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:263 -#, python-format -msgid "Removed repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:268 -#, python-format -msgid "Error occurred during deletion of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:279 -#: rhodecode/controllers/admin/repos_groups.py:314 -#: rhodecode/controllers/admin/users_groups.py:300 -msgid "Cannot revoke permission for yourself as admin" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:294 -msgid "Repository Group permissions updated" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:123 +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 +msgid "An error occurred during unlocking" +msgstr "Une erreur est survenue durant le déverrouillage." + +#: kallithea/controllers/admin/repos.py:595 +msgid "Unlocked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:598 +msgid "Locked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:600 +#, python-format +msgid "Repository has been %s" +msgstr "Le dépôt a été %s." + +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "Une erreur est survenue durant l’invalidation du cache." + +#: kallithea/controllers/admin/repos.py:637 +msgid "Pulled from remote location" +msgstr "Les changements distants ont été récupérés." + +#: kallithea/controllers/admin/repos.py:640 +msgid "An error occurred during pull from remote location" +msgstr "Une erreur est survenue durant le pull depuis la source distante." + +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "Une erreur est survenue durant la suppression des statistiques du dépôt." + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "Réglages des gestionnaires de versions mis à jour." + +#: kallithea/controllers/admin/settings.py:176 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:215 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" msgstr "" -#: rhodecode/controllers/admin/settings.py:132 -msgid "Whoosh reindex task scheduled" -msgstr "La tâche de réindexation Whoosh a été planifiée." - -#: rhodecode/controllers/admin/settings.py:163 +#: kallithea/controllers/admin/settings.py:270 msgid "Updated application settings" msgstr "Réglages mis à jour" -#: rhodecode/controllers/admin/settings.py:167 -#: rhodecode/controllers/admin/settings.py:304 -msgid "Error occurred during updating application settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:219 +#: kallithea/controllers/admin/settings.py:327 msgid "Updated visualisation settings" msgstr "Réglages d’affichage mis à jour." -#: rhodecode/controllers/admin/settings.py:224 +#: kallithea/controllers/admin/settings.py:332 msgid "Error occurred during updating visualisation settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:300 -msgid "Updated VCS settings" -msgstr "Réglages des gestionnaires de versions mis à jour." - -#: rhodecode/controllers/admin/settings.py:314 +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "" + +#: kallithea/controllers/admin/settings.py:400 msgid "Added new hook" msgstr "Le nouveau hook a été ajouté." -#: rhodecode/controllers/admin/settings.py:326 +#: kallithea/controllers/admin/settings.py:414 msgid "Updated hooks" msgstr "Hooks mis à jour" -#: rhodecode/controllers/admin/settings.py:330 +#: kallithea/controllers/admin/settings.py:418 msgid "Error occurred during hook creation" msgstr "" -#: rhodecode/controllers/admin/settings.py:349 -msgid "Email task created" -msgstr "La tâche d’e-mail a été créée." - -#: rhodecode/controllers/admin/settings.py:413 -msgid "You can't edit this user since it's crucial for entire application" -msgstr "Vous ne pouvez pas éditer cet utilisateur ; il est nécessaire pour le bon fonctionnement de l’application." - -#: rhodecode/controllers/admin/settings.py:455 -msgid "Your account was updated successfully" -msgstr "Votre compte a été mis à jour avec succès" - -#: rhodecode/controllers/admin/settings.py:470 -#: rhodecode/controllers/admin/users.py:198 -#, python-format -msgid "Error occurred during update of user %s" -msgstr "" - -#: rhodecode/controllers/admin/users.py:130 +#: kallithea/controllers/admin/settings.py:444 +msgid "Whoosh reindex task scheduled" +msgstr "La tâche de réindexation Whoosh a été planifiée." + +#: kallithea/controllers/admin/user_groups.py:150 +#, python-format +msgid "Created user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:161 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Updated user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:221 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:239 +msgid "Successfully deleted user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:244 +msgid "An error occurred during deletion of user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:311 +msgid "Target group cannot be the same" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:317 +msgid "User Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "Une erreur est survenue durant l’enregistrement des permissions." + +#: kallithea/controllers/admin/users.py:135 #, python-format msgid "Created user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:142 +#: kallithea/controllers/admin/users.py:149 #, python-format msgid "Error occurred during creation of user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:176 +#: kallithea/controllers/admin/users.py:188 msgid "User updated successfully" msgstr "L’utilisateur a été mis à jour avec succès." -#: rhodecode/controllers/admin/users.py:214 +#: kallithea/controllers/admin/users.py:223 msgid "Successfully deleted user" msgstr "" -#: rhodecode/controllers/admin/users.py:219 +#: kallithea/controllers/admin/users.py:228 msgid "An error occurred during deletion of user" msgstr "Une erreur est survenue durant la suppression de l’utilisateur." -#: rhodecode/controllers/admin/users.py:234 +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 msgid "You can't edit this user" msgstr "Vous ne pouvez pas éditer cet utilisateur" -#: rhodecode/controllers/admin/users.py:293 -#: rhodecode/controllers/admin/users_groups.py:372 -msgid "Updated permissions" -msgstr "" - -#: rhodecode/controllers/admin/users.py:297 -#: rhodecode/controllers/admin/users_groups.py:376 -msgid "An error occurred during permissions saving" -msgstr "Une erreur est survenue durant l’enregistrement des permissions." - -#: rhodecode/controllers/admin/users.py:311 -#, python-format -msgid "Added email %s to user" -msgstr "L’e-mail « %s » a été ajouté à l’utilisateur." - -#: rhodecode/controllers/admin/users.py:317 -msgid "An error occurred during email saving" -msgstr "Une erreur est survenue durant l’enregistrement de l’e-mail." - -#: rhodecode/controllers/admin/users.py:327 -msgid "Removed email from user" -msgstr "L’e-mail a été enlevé de l’utilisateur." - -#: rhodecode/controllers/admin/users.py:340 -#, python-format -msgid "Added ip %s to user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:346 +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "" + +#: kallithea/controllers/admin/users.py:489 msgid "An error occurred during ip saving" msgstr "" -#: rhodecode/controllers/admin/users.py:358 -msgid "Removed ip from user" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:162 -#, python-format -msgid "Created user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:173 -#, python-format -msgid "Error occurred during creation of user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:210 -#, python-format -msgid "Updated user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:232 -#, python-format -msgid "Error occurred during update of user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:250 -msgid "Successfully deleted user group" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:255 -msgid "An error occurred during deletion of user group" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:274 -msgid "Target group cannot be the same" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:280 -msgid "User Group permissions updated" -msgstr "" - -#: rhodecode/lib/auth.py:544 +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "" + +#: kallithea/lib/auth.py:748 #, python-format msgid "IP %s not allowed" msgstr "" -#: rhodecode/lib/auth.py:593 +#: kallithea/lib/auth.py:809 msgid "You need to be a registered user to perform this action" msgstr "Vous devez être un utilisateur enregistré pour effectuer cette action." -#: rhodecode/lib/auth.py:634 +#: kallithea/lib/auth.py:846 msgid "You need to be a signed in to view this page" msgstr "Vous devez être connecté pour visualiser cette page." -#: rhodecode/lib/diffs.py:66 +#: kallithea/lib/diffs.py:66 msgid "Binary file" msgstr "" -#: rhodecode/lib/diffs.py:82 -msgid "" -"Changeset was too big and was cut off, use diff menu to display this diff" -msgstr "Cet ensemble de changements était trop gros pour être affiché et a été découpé, utilisez le menu « Diff » pour afficher les différences." - -#: rhodecode/lib/diffs.py:92 +#: kallithea/lib/diffs.py:82 +msgid "Changeset was too big and was cut off, use diff menu to display this diff" +msgstr "" +"Cet ensemble de changements était trop gros pour être affiché et a été " +"découpé, utilisez le menu « Diff » pour afficher les différences." + +#: kallithea/lib/diffs.py:92 msgid "No changes detected" msgstr "Aucun changement détecté." -#: rhodecode/lib/helpers.py:539 -msgid "True" -msgstr "Vrai" - -#: rhodecode/lib/helpers.py:542 -msgid "False" -msgstr "Faux" - -#: rhodecode/lib/helpers.py:580 +#: kallithea/lib/helpers.py:598 #, python-format msgid "Deleted branch: %s" msgstr "" -#: rhodecode/lib/helpers.py:583 +#: kallithea/lib/helpers.py:601 #, python-format msgid "Created tag: %s" msgstr "" -#: rhodecode/lib/helpers.py:596 +#: kallithea/lib/helpers.py:614 msgid "Changeset not found" msgstr "Ensemble de changements non trouvé" -#: rhodecode/lib/helpers.py:646 +#: kallithea/lib/helpers.py:664 #, python-format msgid "Show all combined changesets %s->%s" msgstr "Afficher les changements combinés %s->%s" -#: rhodecode/lib/helpers.py:652 +#: kallithea/lib/helpers.py:670 msgid "compare view" msgstr "vue de comparaison" -#: rhodecode/lib/helpers.py:672 +#: kallithea/lib/helpers.py:690 msgid "and" msgstr "et" -#: rhodecode/lib/helpers.py:673 +#: kallithea/lib/helpers.py:691 #, python-format msgid "%s more" msgstr "%s de plus" -#: rhodecode/lib/helpers.py:674 -#: rhodecode/templates/changelog/changelog.html:53 +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 msgid "revisions" msgstr "révisions" -#: rhodecode/lib/helpers.py:698 +#: kallithea/lib/helpers.py:716 #, python-format msgid "fork name %s" msgstr "" -#: rhodecode/lib/helpers.py:715 -#: rhodecode/templates/pullrequests/pullrequest_show.html:8 +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 #, python-format msgid "Pull request #%s" msgstr "Requête de pull #%s" -#: rhodecode/lib/helpers.py:725 +#: kallithea/lib/helpers.py:743 msgid "[deleted] repository" msgstr "[a supprimé] le dépôt" -#: rhodecode/lib/helpers.py:727 rhodecode/lib/helpers.py:739 +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 msgid "[created] repository" msgstr "[a créé] le dépôt" -#: rhodecode/lib/helpers.py:729 +#: kallithea/lib/helpers.py:747 msgid "[created] repository as fork" msgstr "[a créé] le dépôt en tant que fork" -#: rhodecode/lib/helpers.py:731 rhodecode/lib/helpers.py:741 +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 msgid "[forked] repository" msgstr "[a forké] le dépôt" -#: rhodecode/lib/helpers.py:733 rhodecode/lib/helpers.py:743 +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 msgid "[updated] repository" msgstr "[a mis à jour] le dépôt" -#: rhodecode/lib/helpers.py:735 +#: kallithea/lib/helpers.py:753 msgid "[downloaded] archive from repository" msgstr "" -#: rhodecode/lib/helpers.py:737 +#: kallithea/lib/helpers.py:755 msgid "[delete] repository" msgstr "[a supprimé] le dépôt" -#: rhodecode/lib/helpers.py:745 +#: kallithea/lib/helpers.py:763 msgid "[created] user" msgstr "[a créé] l’utilisateur" -#: rhodecode/lib/helpers.py:747 +#: kallithea/lib/helpers.py:765 msgid "[updated] user" msgstr "[a mis à jour] l’utilisateur" -#: rhodecode/lib/helpers.py:749 +#: kallithea/lib/helpers.py:767 msgid "[created] user group" msgstr "" -#: rhodecode/lib/helpers.py:751 +#: kallithea/lib/helpers.py:769 msgid "[updated] user group" msgstr "" -#: rhodecode/lib/helpers.py:753 +#: kallithea/lib/helpers.py:771 msgid "[commented] on revision in repository" msgstr "[a commenté] une révision du dépôt" -#: rhodecode/lib/helpers.py:755 +#: kallithea/lib/helpers.py:773 msgid "[commented] on pull request for" msgstr "[a commenté] la requête de pull pour" -#: rhodecode/lib/helpers.py:757 +#: kallithea/lib/helpers.py:775 msgid "[closed] pull request for" msgstr "[a fermé] la requête de pull de" -#: rhodecode/lib/helpers.py:759 +#: kallithea/lib/helpers.py:777 msgid "[pushed] into" msgstr "[a pushé] dans" -#: rhodecode/lib/helpers.py:761 -msgid "[committed via RhodeCode] into repository" -msgstr "[a commité via RhodeCode] dans le dépôt" - -#: rhodecode/lib/helpers.py:763 +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "[a commité via Kallithea] dans le dépôt" + +#: kallithea/lib/helpers.py:781 msgid "[pulled from remote] into repository" msgstr "[a pullé depuis un site distant] dans le dépôt" -#: rhodecode/lib/helpers.py:765 +#: kallithea/lib/helpers.py:783 msgid "[pulled] from" msgstr "[a pullé] depuis" -#: rhodecode/lib/helpers.py:767 +#: kallithea/lib/helpers.py:785 msgid "[started following] repository" msgstr "[suit maintenant] le dépôt" -#: rhodecode/lib/helpers.py:769 +#: kallithea/lib/helpers.py:787 msgid "[stopped following] repository" msgstr "[ne suit plus] le dépôt" -#: rhodecode/lib/helpers.py:1088 +#: kallithea/lib/helpers.py:1101 #, python-format msgid " and %s more" msgstr "et %s de plus" -#: rhodecode/lib/helpers.py:1092 +#: kallithea/lib/helpers.py:1105 msgid "No Files" msgstr "Aucun fichier" -#: rhodecode/lib/helpers.py:1158 +#: kallithea/lib/helpers.py:1171 msgid "new file" msgstr "" -#: rhodecode/lib/helpers.py:1161 +#: kallithea/lib/helpers.py:1174 msgid "mod" msgstr "" -#: rhodecode/lib/helpers.py:1164 +#: kallithea/lib/helpers.py:1177 msgid "del" msgstr "" -#: rhodecode/lib/helpers.py:1167 +#: kallithea/lib/helpers.py:1180 msgid "rename" msgstr "" -#: rhodecode/lib/helpers.py:1172 +#: kallithea/lib/helpers.py:1185 msgid "chmod" msgstr "" -#: rhodecode/lib/helpers.py:1404 +#: kallithea/lib/helpers.py:1417 #, python-format msgid "" -"%s repository is not mapped to db perhaps it was created or renamed from the" -" filesystem please run the application again in order to rescan repositories" -msgstr "Le dépôt %s n’est pas représenté dans la base de données. Il a probablement été créé ou renommé manuellement. Veuillez relancer l’application pour rescanner les dépôts." - -#: rhodecode/lib/unionrepo.py:193 -msgid "cannot create new union repository" -msgstr "" - -#: rhodecode/lib/utils2.py:410 +"%s repository is not mapped to db perhaps it was created or renamed from " +"the filesystem please run the application again in order to rescan " +"repositories" +msgstr "" +"Le dépôt %s n’est pas représenté dans la base de données. Il a " +"probablement été créé ou renommé manuellement. Veuillez relancer " +"l’application pour rescanner les dépôts." + +#: kallithea/lib/utils2.py:415 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d an" msgstr[1] "%d ans" -#: rhodecode/lib/utils2.py:411 +#: kallithea/lib/utils2.py:416 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d mois" msgstr[1] "%d mois" -#: rhodecode/lib/utils2.py:412 +#: kallithea/lib/utils2.py:417 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d jour" msgstr[1] "%d jours" -#: rhodecode/lib/utils2.py:413 +#: kallithea/lib/utils2.py:418 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d heure" msgstr[1] "%d heures" -#: rhodecode/lib/utils2.py:414 +#: kallithea/lib/utils2.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minute" msgstr[1] "%d minutes" -#: rhodecode/lib/utils2.py:415 +#: kallithea/lib/utils2.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d seconde" msgstr[1] "%d secondes" -#: rhodecode/lib/utils2.py:431 +#: kallithea/lib/utils2.py:436 #, python-format msgid "in %s" msgstr "" -#: rhodecode/lib/utils2.py:433 +#: kallithea/lib/utils2.py:438 #, python-format msgid "%s ago" msgstr "Il y a %s" -#: rhodecode/lib/utils2.py:435 +#: kallithea/lib/utils2.py:440 #, python-format msgid "in %s and %s" msgstr "" -#: rhodecode/lib/utils2.py:438 +#: kallithea/lib/utils2.py:443 #, python-format msgid "%s and %s ago" msgstr "Il y a %s et %s" -#: rhodecode/lib/utils2.py:441 +#: kallithea/lib/utils2.py:446 msgid "just now" msgstr "à l’instant" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1163 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1303 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1388 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1408 rhodecode/model/db.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 msgid "Repository no access" msgstr "Aucun accès au dépôt" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1164 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1184 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1304 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1389 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1409 rhodecode/model/db.py:1414 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 msgid "Repository read access" msgstr "Accès en lecture au dépôt" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1165 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1185 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1305 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1390 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1410 rhodecode/model/db.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 msgid "Repository write access" msgstr "Accès en écriture au dépôt" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1166 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1186 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1306 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1391 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1411 rhodecode/model/db.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 msgid "Repository admin access" msgstr "Accès administrateur au dépôt" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1168 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 msgid "Repositories Group no access" msgstr "Aucun accès au groupe de dépôts" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1169 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1309 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 msgid "Repositories Group read access" msgstr "Accès en lecture au groupe de dépôts" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1170 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1310 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 msgid "Repositories Group write access" msgstr "Accès en écriture au groupe de dépôts" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1171 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1311 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 msgid "Repositories Group admin access" msgstr "Accès administrateur au groupe de dépôts" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1173 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1193 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1313 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1398 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1406 rhodecode/model/db.py:1411 -msgid "RhodeCode Administrator" -msgstr "Administrateur RhodeCode" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1174 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1194 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1314 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1399 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1429 rhodecode/model/db.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" +msgstr "Administrateur Kallithea" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 msgid "Repository creation disabled" msgstr "Création de dépôt désactivée" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1175 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1195 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1315 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1400 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1430 rhodecode/model/db.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 msgid "Repository creation enabled" msgstr "Création de dépôt activée" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1176 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1196 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1316 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1401 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1432 rhodecode/model/db.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 msgid "Repository forking disabled" msgstr "Fork de dépôt désactivé" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1177 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1197 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1317 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1402 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1433 rhodecode/model/db.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 msgid "Repository forking enabled" msgstr "Fork de dépôt activé" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1178 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1318 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 msgid "Register disabled" msgstr "Enregistrement désactivé" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1319 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1404 -msgid "Register new user with RhodeCode with manual activation" -msgstr "Enregistrer un nouvel utilisateur Rhodecode manuellement activé" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1202 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1407 -msgid "Register new user with RhodeCode with auto activation" -msgstr "Enregistrer un nouvel utilisateur Rhodecode auto-activé" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1623 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1643 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1763 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1838 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1934 rhodecode/model/db.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" +msgstr "Enregistrer un nouvel utilisateur Kallithea manuellement activé" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" +msgstr "Enregistrer un nouvel utilisateur Kallithea auto-activé" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 msgid "Not Reviewed" msgstr "Pas encore relue" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1624 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1644 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1764 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1839 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1935 rhodecode/model/db.py:1940 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 msgid "Approved" msgstr "Approuvée " -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1625 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1645 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1765 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1840 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1936 rhodecode/model/db.py:1941 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 msgid "Rejected" msgstr "Rejetée" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1626 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1646 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1766 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1841 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1937 rhodecode/model/db.py:1942 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 msgid "Under Review" msgstr "En cours de relecture" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1252 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1270 rhodecode/model/db.py:1275 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 msgid "top level" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1393 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1413 rhodecode/model/db.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 msgid "Repository group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1394 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1414 rhodecode/model/db.py:1419 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 msgid "Repository group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1395 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1415 rhodecode/model/db.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 msgid "Repository group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1396 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1416 rhodecode/model/db.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 msgid "Repository group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1418 rhodecode/model/db.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 msgid "User group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1419 rhodecode/model/db.py:1424 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 msgid "User group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1420 rhodecode/model/db.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 msgid "User group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1421 rhodecode/model/db.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 msgid "User group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1423 rhodecode/model/db.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 msgid "Repository Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1424 rhodecode/model/db.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 msgid "Repository Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1426 rhodecode/model/db.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 msgid "User Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1427 rhodecode/model/db.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 msgid "User Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1435 rhodecode/model/db.py:1440 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 msgid "Registration disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1436 rhodecode/model/db.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 msgid "User Registration with manual account activation" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1437 rhodecode/model/db.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 msgid "User Registration with automatic account activation" msgstr "" -#: rhodecode/model/comment.py:75 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:77 #, python-format msgid "on line %s" msgstr "à la ligne %s" -#: rhodecode/model/comment.py:220 +#: kallithea/model/comment.py:222 msgid "[Mention]" msgstr "[Mention]" -#: rhodecode/model/forms.py:43 +#: kallithea/model/forms.py:57 msgid "Please enter a login" msgstr "Veuillez entrer un identifiant" -#: rhodecode/model/forms.py:44 +#: kallithea/model/forms.py:58 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "Entrez une valeur d’au moins %(min)i caractères de long." -#: rhodecode/model/forms.py:52 +#: kallithea/model/forms.py:66 msgid "Please enter a password" msgstr "Veuillez entrer un mot de passe" -#: rhodecode/model/forms.py:53 +#: kallithea/model/forms.py:67 #, python-format msgid "Enter %(min)i characters or more" msgstr "Entrez au moins %(min)i caractères" -#: rhodecode/model/notification.py:228 +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:231 #, python-format msgid "%(user)s commented on changeset at %(when)s" msgstr "" -#: rhodecode/model/notification.py:229 +#: kallithea/model/notification.py:232 #, python-format msgid "%(user)s sent message at %(when)s" msgstr "" -#: rhodecode/model/notification.py:230 +#: kallithea/model/notification.py:233 #, python-format msgid "%(user)s mentioned you at %(when)s" msgstr "" -#: rhodecode/model/notification.py:231 -#, python-format -msgid "%(user)s registered in RhodeCode at %(when)s" -msgstr "" - -#: rhodecode/model/notification.py:232 +#: kallithea/model/notification.py:234 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:235 #, python-format msgid "%(user)s opened new pull request at %(when)s" msgstr "" -#: rhodecode/model/notification.py:233 +#: kallithea/model/notification.py:236 #, python-format msgid "%(user)s commented on pull request at %(when)s" msgstr "" -#: rhodecode/model/pull_request.py:98 +#: kallithea/model/pull_request.py:107 #, python-format msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" msgstr "" -#: rhodecode/model/scm.py:674 +#: kallithea/model/scm.py:810 msgid "latest tip" msgstr "Dernier sommet" -#: rhodecode/model/user.py:232 +#: kallithea/model/user.py:198 msgid "New user registration" msgstr "" -#: rhodecode/model/user.py:257 rhodecode/model/user.py:281 +#: kallithea/model/user.py:222 kallithea/model/user.py:247 msgid "You can't Edit this user since it's crucial for entire application" -msgstr "Vous ne pouvez pas éditer cet utilisateur ; il est nécessaire pour le bon fonctionnement de l’application." - -#: rhodecode/model/user.py:303 +msgstr "" +"Vous ne pouvez pas éditer cet utilisateur ; il est nécessaire pour le bon" +" fonctionnement de l’application." + +#: kallithea/model/user.py:270 msgid "You can't remove this user since it's crucial for entire application" -msgstr "Vous ne pouvez pas supprimer cet utilisateur ; il est nécessaire pour le bon fonctionnement de l’application." - -#: rhodecode/model/user.py:309 +msgstr "" +"Vous ne pouvez pas supprimer cet utilisateur ; il est nécessaire pour le " +"bon fonctionnement de l’application." + +#: kallithea/model/user.py:276 #, python-format msgid "" -"user \"%s\" still owns %s repositories and cannot be removed. Switch owners " -"or remove those repositories. %s" -msgstr "L’utilisateur « %s » possède %s dépôts et ne peut être supprimé. Changez les propriétaires de ces dépôts. %s" - -#: rhodecode/model/user.py:334 +"user \"%s\" still owns %s repositories and cannot be removed. Switch " +"owners or remove those repositories. %s" +msgstr "" +"L’utilisateur « %s » possède %s dépôts et ne peut être supprimé. Changez " +"les propriétaires de ces dépôts. %s" + +#: kallithea/model/user.py:304 msgid "Password reset link" msgstr "" -#: rhodecode/model/user.py:366 +#: kallithea/model/user.py:333 msgid "Your new password" msgstr "" -#: rhodecode/model/user.py:367 -#, python-format -msgid "Your new RhodeCode password:%s" -msgstr "" - -#: rhodecode/model/validators.py:38 rhodecode/model/validators.py:39 +#: kallithea/model/user.py:334 +#, python-format +msgid "Your new Kallithea password:%s" +msgstr "" + +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 msgid "Value cannot be an empty list" msgstr "Cette valeur ne peut être une liste vide." -#: rhodecode/model/validators.py:85 +#: kallithea/model/validators.py:120 #, python-format msgid "Username \"%(username)s\" already exists" msgstr "Le nom d’utilisateur « %(username)s » existe déjà." -#: rhodecode/model/validators.py:87 +#: kallithea/model/validators.py:122 #, python-format msgid "Username \"%(username)s\" is forbidden" msgstr "Le nom d’utilisateur « %(username)s » n’est pas autorisé" -#: rhodecode/model/validators.py:89 +#: kallithea/model/validators.py:124 msgid "" -"Username may only contain alphanumeric characters underscores, periods or " -"dashes and must begin with alphanumeric character or underscore" -msgstr "" - -#: rhodecode/model/validators.py:117 +"Username may only contain alphanumeric characters underscores, periods or" +" dashes and must begin with alphanumeric character or underscore" +msgstr "" + +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:158 #, python-format msgid "Username %(username)s is not valid" msgstr "Le nom d’utilisateur « %(username)s » n’est pas valide." -#: rhodecode/model/validators.py:136 +#: kallithea/model/validators.py:177 msgid "Invalid user group name" msgstr "" -#: rhodecode/model/validators.py:137 +#: kallithea/model/validators.py:178 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:139 +#: kallithea/model/validators.py:180 msgid "" "user group name may only contain alphanumeric characters underscores, " "periods or dashes and must begin with alphanumeric character" msgstr "" -#: rhodecode/model/validators.py:177 +#: kallithea/model/validators.py:218 msgid "Cannot assign this group as parent" msgstr "Impossible d’assigner ce groupe en tant que parent." -#: rhodecode/model/validators.py:178 +#: kallithea/model/validators.py:219 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "Le groupe « %(group_name)s » existe déjà." -#: rhodecode/model/validators.py:180 +#: kallithea/model/validators.py:221 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "Un dépôt portant le nom « %(group_name)s » existe déjà." -#: rhodecode/model/validators.py:238 +#: kallithea/model/validators.py:279 msgid "Invalid characters (non-ascii) in password" msgstr "Caractères incorrects (non-ASCII) dans le mot de passe." -#: rhodecode/model/validators.py:253 +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 msgid "Passwords do not match" msgstr "Les mots de passe ne correspondent pas." -#: rhodecode/model/validators.py:270 +#: kallithea/model/validators.py:327 msgid "invalid password" msgstr "mot de passe invalide" -#: rhodecode/model/validators.py:271 +#: kallithea/model/validators.py:328 msgid "invalid user name" msgstr "nom d’utilisateur invalide" -#: rhodecode/model/validators.py:272 +#: kallithea/model/validators.py:329 msgid "Your account is disabled" msgstr "Votre compte est désactivé" -#: rhodecode/model/validators.py:316 +#: kallithea/model/validators.py:373 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "Le nom de dépôt « %(repo)s » n’est pas autorisé." -#: rhodecode/model/validators.py:318 +#: kallithea/model/validators.py:375 #, python-format msgid "Repository named %(repo)s already exists" msgstr "Un dépôt portant le nom « %(repo)s » existe déjà." -#: rhodecode/model/validators.py:319 +#: kallithea/model/validators.py:376 #, python-format msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" msgstr "Le dépôt « %(repo)s » existe déjà dans le groupe « %(group)s »." -#: rhodecode/model/validators.py:321 +#: kallithea/model/validators.py:378 #, python-format msgid "Repository group with name \"%(repo)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:438 +#: kallithea/model/validators.py:493 msgid "invalid clone url" msgstr "URL de clonage invalide." -#: rhodecode/model/validators.py:439 +#: kallithea/model/validators.py:494 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" -msgstr "URL à cloner invalide. Veuillez fournir une URL valide en http(s) ou svn+http(s)." - -#: rhodecode/model/validators.py:464 +msgstr "" +"URL à cloner invalide. Veuillez fournir une URL valide en http(s) ou " +"svn+http(s)." + +#: kallithea/model/validators.py:519 msgid "Fork have to be the same type as parent" msgstr "Le fork doit être du même type que le parent." -#: rhodecode/model/validators.py:479 +#: kallithea/model/validators.py:534 msgid "You don't have permissions to create repository in this group" msgstr "Vous n’avez pas la permission de créer un dépôt dans ce groupe." -#: rhodecode/model/validators.py:481 +#: kallithea/model/validators.py:536 msgid "no permission to create repository in root location" msgstr "" -#: rhodecode/model/validators.py:518 +#: kallithea/model/validators.py:585 msgid "You don't have permissions to create a group in this location" msgstr "" -#: rhodecode/model/validators.py:559 +#: kallithea/model/validators.py:626 msgid "This username or user group name is not valid" msgstr "" -#: rhodecode/model/validators.py:652 +#: kallithea/model/validators.py:719 msgid "This is not a valid path" msgstr "Ceci n’est pas un chemin valide" -#: rhodecode/model/validators.py:667 +#: kallithea/model/validators.py:734 msgid "This e-mail address is already taken" msgstr "Cette adresse e-mail est déjà enregistrée" -#: rhodecode/model/validators.py:687 +#: kallithea/model/validators.py:754 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "L’adresse e-mail « %(email)s » n’existe pas" -#: rhodecode/model/validators.py:724 +#: kallithea/model/validators.py:791 msgid "" -"The LDAP Login attribute of the CN must be specified - this is the name of " -"the attribute that is equivalent to \"username\"" -msgstr "L’attribut Login du CN doit être spécifié. Cet attribut correspond au nom d’utilisateur." - -#: rhodecode/model/validators.py:737 +"The LDAP Login attribute of the CN must be specified - this is the name " +"of the attribute that is equivalent to \"username\"" +msgstr "" +"L’attribut Login du CN doit être spécifié. Cet attribut correspond au nom" +" d’utilisateur." + +#: kallithea/model/validators.py:804 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" -msgstr "Les révisions %(revs)s font déjà partie de la requête de pull ou on des statuts définis." - -#: rhodecode/model/validators.py:769 +msgstr "" +"Les révisions %(revs)s font déjà partie de la requête de pull ou on des " +"statuts définis." + +#: kallithea/model/validators.py:836 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "" -#: rhodecode/model/validators.py:770 -#, python-format -msgid "" -"The network size (bits) must be within the range of 0-32 (not %(bits)r)" -msgstr "" - -#: rhodecode/model/validators.py:803 +#: kallithea/model/validators.py:837 +#, python-format +msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" +msgstr "" + +#: kallithea/model/validators.py:870 msgid "Key name can only consist of letters, underscore, dash or numbers" msgstr "" -#: rhodecode/model/validators.py:817 +#: kallithea/model/validators.py:884 msgid "Filename cannot be inside a directory" msgstr "" -#: rhodecode/templates/index.html:5 +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" +msgstr "" + +#: kallithea/templates/index.html:5 msgid "Dashboard" msgstr "Tableau de bord" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/repo_switcher_list.html:4 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/users/user_edit_my_account.html:31 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/bookmarks/bookmarks.html:9 -#: rhodecode/templates/branches/branches.html:9 -#: rhodecode/templates/journal/journal.html:9 -#: rhodecode/templates/journal/journal.html:46 -#: rhodecode/templates/journal/journal.html:47 -#: rhodecode/templates/tags/tags.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 msgid "quick filter..." msgstr "Filtre rapide…" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/admin/repos/repos.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 msgid "repositories" msgstr "Dépôts" -#: rhodecode/templates/index_base.html:13 -#: rhodecode/templates/index_base.html:18 -#: rhodecode/templates/admin/repos/repo_add.html:5 -#: rhodecode/templates/admin/repos/repos.html:22 -msgid "Add repository" -msgstr "Ajouter un dépôt" - -#: rhodecode/templates/index_base.html:15 -#: rhodecode/templates/index_base.html:20 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:31 -msgid "Add group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 -msgid "Edit group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" +msgstr "" + +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:32 msgid "You have admin right to this group, and can edit it" msgstr "" -#: rhodecode/templates/index_base.html:40 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:33 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:38 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:43 -#: rhodecode/templates/admin/users_groups/users_group_add.html:32 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 -#: rhodecode/templates/admin/users_groups/users_groups.html:37 -msgid "Group name" -msgstr "Nom de groupe" - -#: rhodecode/templates/index_base.html:41 -#: rhodecode/templates/index_base.html:123 -#: rhodecode/templates/admin/repos/repo_add_base.html:56 -#: rhodecode/templates/admin/repos/repo_edit.html:68 -#: rhodecode/templates/admin/repos/repos.html:75 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:42 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:47 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:44 -#: rhodecode/templates/email_templates/changeset_comment.html:9 -#: rhodecode/templates/email_templates/pull_request.html:9 -#: rhodecode/templates/forks/fork.html:56 -#: rhodecode/templates/pullrequests/pullrequest.html:43 -#: rhodecode/templates/pullrequests/pullrequest_show.html:81 -#: rhodecode/templates/summary/summary.html:106 +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" +msgstr "" + +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 msgid "Description" msgstr "Description" -#: rhodecode/templates/index_base.html:51 -#: rhodecode/templates/admin/permissions/permissions.html:55 -#: rhodecode/templates/admin/repos/repo_add_base.html:29 -#: rhodecode/templates/admin/repos/repo_edit.html:50 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:57 -#: rhodecode/templates/forks/fork.html:47 -msgid "Repository group" -msgstr "Groupe de dépôt" - -#: rhodecode/templates/index_base.html:121 -#: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit.html:32 -#: rhodecode/templates/admin/repos/repos.html:73 -#: rhodecode/templates/admin/users/user_edit_my_account.html:172 -#: rhodecode/templates/base/perms_summary.html:37 -#: rhodecode/templates/bookmarks/bookmarks.html:48 -#: rhodecode/templates/bookmarks/bookmarks_data.html:6 -#: rhodecode/templates/branches/branches.html:47 -#: rhodecode/templates/branches/branches_data.html:6 -#: rhodecode/templates/files/files_browser.html:47 -#: rhodecode/templates/journal/journal.html:193 -#: rhodecode/templates/journal/journal.html:283 -#: rhodecode/templates/summary/summary.html:55 -#: rhodecode/templates/summary/summary.html:124 -#: rhodecode/templates/tags/tags.html:48 -#: rhodecode/templates/tags/tags_data.html:6 +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 msgid "Name" msgstr "Nom" -#: rhodecode/templates/index_base.html:124 +#: kallithea/templates/index_base.html:129 msgid "Last Change" msgstr "Dernière modification" -#: rhodecode/templates/index_base.html:126 -#: rhodecode/templates/admin/repos/repos.html:76 -#: rhodecode/templates/admin/users/user_edit_my_account.html:174 -#: rhodecode/templates/journal/journal.html:195 -#: rhodecode/templates/journal/journal.html:285 +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 msgid "Tip" msgstr "Sommet" -#: rhodecode/templates/index_base.html:128 -#: rhodecode/templates/admin/repos/repo_edit.html:114 -#: rhodecode/templates/admin/repos/repos.html:78 +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 msgid "Owner" msgstr "Propriétaire" -#: rhodecode/templates/index_base.html:136 -#: rhodecode/templates/admin/repos/repos.html:86 -#: rhodecode/templates/admin/users/user_edit_my_account.html:183 -#: rhodecode/templates/admin/users/users.html:107 -#: rhodecode/templates/bookmarks/bookmarks.html:74 -#: rhodecode/templates/branches/branches.html:73 -#: rhodecode/templates/journal/journal.html:204 -#: rhodecode/templates/journal/journal.html:294 -#: rhodecode/templates/tags/tags.html:74 +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 msgid "Click to sort ascending" msgstr "Tri ascendant" -#: rhodecode/templates/index_base.html:137 -#: rhodecode/templates/admin/repos/repos.html:87 -#: rhodecode/templates/admin/users/user_edit_my_account.html:184 -#: rhodecode/templates/admin/users/users.html:108 -#: rhodecode/templates/bookmarks/bookmarks.html:75 -#: rhodecode/templates/branches/branches.html:74 -#: rhodecode/templates/journal/journal.html:205 -#: rhodecode/templates/journal/journal.html:295 -#: rhodecode/templates/tags/tags.html:75 +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 msgid "Click to sort descending" msgstr "Tri descendant" -#: rhodecode/templates/index_base.html:138 +#: kallithea/templates/index_base.html:143 msgid "No repositories found." msgstr "" -#: rhodecode/templates/index_base.html:139 -#: rhodecode/templates/admin/repos/repos.html:89 -#: rhodecode/templates/admin/users/user_edit_my_account.html:186 -#: rhodecode/templates/admin/users/users.html:110 -#: rhodecode/templates/bookmarks/bookmarks.html:77 -#: rhodecode/templates/branches/branches.html:76 -#: rhodecode/templates/journal/journal.html:207 -#: rhodecode/templates/journal/journal.html:297 -#: rhodecode/templates/tags/tags.html:77 +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 msgid "Data error." msgstr "Erreur d’intégrité des données." -#: rhodecode/templates/index_base.html:140 -#: rhodecode/templates/admin/repos/repos.html:90 -#: rhodecode/templates/admin/users/user_edit_my_account.html:58 -#: rhodecode/templates/admin/users/user_edit_my_account.html:187 -#: rhodecode/templates/admin/users/users.html:111 -#: rhodecode/templates/bookmarks/bookmarks.html:78 -#: rhodecode/templates/branches/branches.html:77 -#: rhodecode/templates/journal/journal.html:208 -#: rhodecode/templates/journal/journal.html:298 -#: rhodecode/templates/tags/tags.html:78 +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 msgid "Loading..." msgstr "Chargement…" -#: rhodecode/templates/login.html:5 rhodecode/templates/base/base.html:239 +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 msgid "Log In" msgstr "Connexion" -#: rhodecode/templates/login.html:21 +#: kallithea/templates/login.html:30 #, python-format msgid "Log In to %s" msgstr "" -#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20 -#: rhodecode/templates/admin/admin_log.html:5 -#: rhodecode/templates/admin/users/user_add.html:32 -#: rhodecode/templates/admin/users/user_edit.html:57 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:31 -#: rhodecode/templates/admin/users/users.html:77 -#: rhodecode/templates/base/base.html:215 -#: rhodecode/templates/summary/summary.html:123 +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 msgid "Username" msgstr "Nom d’utilisateur" -#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29 -#: rhodecode/templates/admin/ldap/ldap.html:46 -#: rhodecode/templates/admin/users/user_add.html:41 -#: rhodecode/templates/base/base.html:224 +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 msgid "Password" msgstr "Mot de passe" -#: rhodecode/templates/login.html:50 +#: kallithea/templates/login.html:62 msgid "Remember me" msgstr "Se souvenir de moi" -#: rhodecode/templates/login.html:54 +#: kallithea/templates/login.html:66 msgid "Sign In" msgstr "Connexion" -#: rhodecode/templates/login.html:60 +#: kallithea/templates/login.html:72 msgid "Forgot your password ?" msgstr "Mot de passe oublié ?" -#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:235 +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 msgid "Don't have an account ?" msgstr "Vous n’avez pas de compte ?" -#: rhodecode/templates/password_reset.html:5 +#: kallithea/templates/password_reset.html:5 msgid "Password Reset" msgstr "" -#: rhodecode/templates/password_reset.html:11 -msgid "Reset your password to" -msgstr "Réinitialiser votre mot de passe" - -#: rhodecode/templates/password_reset.html:21 -msgid "Email address" -msgstr "Adresse e-mail" - -#: rhodecode/templates/password_reset.html:30 -msgid "Reset my password" -msgstr "Réinitialiser mon mot de passe" - -#: rhodecode/templates/password_reset.html:31 +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" +msgstr "" + +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "" + +#: kallithea/templates/password_reset.html:64 msgid "Password reset link will be send to matching email address" msgstr "Votre nouveau mot de passe sera envoyé à l’adresse correspondante." -#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74 +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 msgid "Sign Up" msgstr "Inscription" -#: rhodecode/templates/register.html:11 -msgid "Sign Up to" -msgstr "Inscription à" - -#: rhodecode/templates/register.html:38 +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:58 msgid "Re-enter password" msgstr "Confirmation" -#: rhodecode/templates/register.html:47 -#: rhodecode/templates/admin/users/user_add.html:59 -#: rhodecode/templates/admin/users/user_edit.html:97 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:62 +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 msgid "First Name" msgstr "Prénom" -#: rhodecode/templates/register.html:56 -#: rhodecode/templates/admin/users/user_add.html:68 -#: rhodecode/templates/admin/users/user_edit.html:106 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:71 +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 msgid "Last Name" msgstr "Nom" -#: rhodecode/templates/register.html:65 -#: rhodecode/templates/admin/users/user_add.html:77 -#: rhodecode/templates/admin/users/user_edit.html:115 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:80 -#: rhodecode/templates/summary/summary.html:125 +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 msgid "Email" msgstr "E-mail" -#: rhodecode/templates/register.html:76 +#: kallithea/templates/register.html:108 msgid "Your account will be activated right after registration" msgstr "Votre compte utilisateur sera actif dès la fin de l’enregistrement." -#: rhodecode/templates/register.html:78 +#: kallithea/templates/register.html:110 msgid "Your account must wait for activation by administrator" msgstr "Votre compte utilisateur devra être activé par un administrateur." -#: rhodecode/templates/repo_switcher_list.html:10 -#: rhodecode/templates/admin/defaults/defaults.html:44 -#: rhodecode/templates/admin/repos/repo_add_base.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:78 -#: rhodecode/templates/data_table/_dt_elements.html:61 -#: rhodecode/templates/summary/summary.html:77 -msgid "Private repository" -msgstr "Dépôt privé" - -#: rhodecode/templates/repo_switcher_list.html:12 -#: rhodecode/templates/data_table/_dt_elements.html:63 -#: rhodecode/templates/summary/summary.html:79 -msgid "Public repository" -msgstr "Dépôt public" - -#: rhodecode/templates/switch_to_list.html:10 -#: rhodecode/templates/branches/branches_data.html:57 +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 msgid "There are no branches yet" msgstr "Aucune branche n’a été créée pour le moment." -#: rhodecode/templates/switch_to_list.html:22 -#: rhodecode/templates/tags/tags_data.html:38 +#: kallithea/templates/switch_to_list.html:16 +msgid "Closed Branches" +msgstr "" + +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 msgid "There are no tags yet" msgstr "Aucun tag n’a été créé pour le moment." -#: rhodecode/templates/switch_to_list.html:35 -#: rhodecode/templates/bookmarks/bookmarks_data.html:37 +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 msgid "There are no bookmarks yet" msgstr "Aucun signet n’a été créé." -#: rhodecode/templates/admin/admin.html:5 -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/base/base.html:73 +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 msgid "Admin journal" msgstr "Historique d’administration" -#: rhodecode/templates/admin/admin.html:10 +#: kallithea/templates/admin/admin.html:13 msgid "journal filter..." msgstr "" -#: rhodecode/templates/admin/admin.html:12 -#: rhodecode/templates/journal/journal.html:11 +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 msgid "filter" msgstr "" -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 #, python-format msgid "%s entry" msgid_plural "%s entries" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/admin/admin_log.html:6 -#: rhodecode/templates/admin/repos/repos.html:79 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46 -#: rhodecode/templates/admin/users/user_edit_my_account.html:176 -#: rhodecode/templates/admin/users/users.html:87 -#: rhodecode/templates/admin/users_groups/users_groups.html:40 -#: rhodecode/templates/journal/journal.html:197 -#: rhodecode/templates/journal/journal.html:287 +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 msgid "Action" msgstr "Action" -#: rhodecode/templates/admin/admin_log.html:7 -#: rhodecode/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" msgstr "Dépôt" -#: rhodecode/templates/admin/admin_log.html:8 -#: rhodecode/templates/bookmarks/bookmarks.html:49 -#: rhodecode/templates/bookmarks/bookmarks_data.html:7 -#: rhodecode/templates/branches/branches.html:48 -#: rhodecode/templates/branches/branches_data.html:7 -#: rhodecode/templates/tags/tags.html:49 -#: rhodecode/templates/tags/tags_data.html:7 +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 msgid "Date" msgstr "Date" -#: rhodecode/templates/admin/admin_log.html:9 +#: kallithea/templates/admin/admin_log.html:9 msgid "From IP" msgstr "Depuis l’adresse IP" -#: rhodecode/templates/admin/admin_log.html:63 +#: kallithea/templates/admin/admin_log.html:63 msgid "No actions yet" msgstr "Aucune action n’a été enregistrée pour le moment." -#: rhodecode/templates/admin/defaults/defaults.html:5 -#: rhodecode/templates/admin/defaults/defaults.html:25 +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "" +"Comma separated list of plugins. Order of plugins is also order in which " +"Kallithea will try to authenticate user" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "Enregistrer" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 msgid "Repositories defaults" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:11 -#: rhodecode/templates/base/base.html:80 +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 msgid "Defaults" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:35 -#: rhodecode/templates/admin/repos/repo_add_base.html:38 +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 msgid "Type" msgstr "Type" -#: rhodecode/templates/admin/defaults/defaults.html:48 -#: rhodecode/templates/admin/repos/repo_add_base.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:82 -#: rhodecode/templates/forks/fork.html:69 +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "Dépôt privé" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 msgid "" "Private repositories are only visible to people explicitly added as " "collaborators." -msgstr "Les dépôts privés sont visibles seulement par les utilisateurs ajoutés comme collaborateurs." - -#: rhodecode/templates/admin/defaults/defaults.html:55 -#: rhodecode/templates/admin/repos/repo_edit.html:87 +msgstr "" +"Les dépôts privés sont visibles seulement par les utilisateurs ajoutés " +"comme collaborateurs." + +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 msgid "Enable statistics" msgstr "Activer les statistiques" -#: rhodecode/templates/admin/defaults/defaults.html:59 -#: rhodecode/templates/admin/repos/repo_edit.html:91 +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." msgstr "Afficher les statistiques sur la page du dépôt." -#: rhodecode/templates/admin/defaults/defaults.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:96 +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 msgid "Enable downloads" msgstr "Activer les téléchargements" -#: rhodecode/templates/admin/defaults/defaults.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:100 +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." msgstr "Afficher le menu de téléchargements sur la page du dépôt." -#: rhodecode/templates/admin/defaults/defaults.html:75 -#: rhodecode/templates/admin/repos/repo_edit.html:105 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:64 +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 msgid "Enable locking" msgstr "Activer le verrouillage" -#: rhodecode/templates/admin/defaults/defaults.html:79 -#: rhodecode/templates/admin/repos/repo_edit.html:109 +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 msgid "Enable lock-by-pulling on repository." msgstr "Activer le verrouillage lors d’un pull sur le dépôt." -#: rhodecode/templates/admin/defaults/defaults.html:84 -#: rhodecode/templates/admin/ldap/ldap.html:89 -#: rhodecode/templates/admin/permissions/permissions.html:122 -#: rhodecode/templates/admin/repos/repo_edit.html:141 -#: rhodecode/templates/admin/repos/repo_edit.html:166 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:72 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:96 -#: rhodecode/templates/admin/settings/hooks.html:73 -#: rhodecode/templates/admin/users/user_add.html:94 -#: rhodecode/templates/admin/users/user_edit.html:140 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:88 -#: rhodecode/templates/admin/users_groups/users_group_add.html:49 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:143 -#: rhodecode/templates/base/default_perms_box.html:53 -msgid "Save" -msgstr "Enregistrer" - -#: rhodecode/templates/admin/gists/index.html:5 -#: rhodecode/templates/base/base.html:299 -msgid "Gists" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "" +"Gist was update since you started editing. Copy your changes and click " +"%(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 #, python-format msgid "Private Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:12 +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 #, python-format msgid "Public Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:14 +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 msgid "Public Gists" msgstr "" -#: rhodecode/templates/admin/gists/index.html:31 -#: rhodecode/templates/admin/gists/show.html:24 -#: rhodecode/templates/base/base.html:302 -msgid "Create new gist" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:48 +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 msgid "Created" msgstr "" -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/index.html:53 -#: rhodecode/templates/admin/gists/show.html:43 -#: rhodecode/templates/admin/gists/show.html:45 -msgid "Expires" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/show.html:43 -msgid "never" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:68 +#: kallithea/templates/admin/gists/index.html:77 msgid "There are no gists yet" msgstr "" -#: rhodecode/templates/admin/gists/new.html:5 -#: rhodecode/templates/admin/gists/new.html:16 -msgid "New gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:37 -msgid "Gist description ..." -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:52 -msgid "Create private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:53 -msgid "Create public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:54 -#: rhodecode/templates/admin/permissions/permissions.html:123 -#: rhodecode/templates/admin/permissions/permissions.html:185 -#: rhodecode/templates/admin/repos/repo_edit.html:142 -#: rhodecode/templates/admin/repos/repo_edit.html:167 -#: rhodecode/templates/admin/repos/repo_edit.html:381 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:97 -#: rhodecode/templates/admin/settings/settings.html:115 -#: rhodecode/templates/admin/settings/settings.html:196 -#: rhodecode/templates/admin/settings/settings.html:288 -#: rhodecode/templates/admin/users/user_edit.html:141 -#: rhodecode/templates/admin/users/user_edit.html:198 -#: rhodecode/templates/admin/users/user_edit.html:246 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:89 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:144 -#: rhodecode/templates/base/default_perms_box.html:54 -#: rhodecode/templates/files/files_add.html:80 -#: rhodecode/templates/files/files_edit.html:66 -#: rhodecode/templates/pullrequests/pullrequest.html:86 +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 msgid "Reset" msgstr "Réinitialiser" -#: rhodecode/templates/admin/gists/show.html:5 -msgid "gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:9 +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 msgid "Gist" msgstr "" -#: rhodecode/templates/admin/gists/show.html:36 -msgid "Public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:38 -msgid "Private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:54 -#: rhodecode/templates/admin/repos/repo_edit.html:299 -#: rhodecode/templates/changeset/changeset_file_comment.html:40 +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 msgid "Delete" msgstr "Supprimer" -#: rhodecode/templates/admin/gists/show.html:54 -msgid "Confirm to delete this gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:63 -#: rhodecode/templates/admin/gists/show.html:84 -#: rhodecode/templates/files/files_edit.html:48 -#: rhodecode/templates/files/files_source.html:25 -#: rhodecode/templates/files/files_source.html:55 -msgid "Show as raw" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:71 +#: kallithea/templates/admin/gists/show.html:59 +msgid "Confirm to delete this Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:76 msgid "created" msgstr "" -#: rhodecode/templates/admin/ldap/ldap.html:5 -msgid "LDAP administration" -msgstr "Administration LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:11 -#: rhodecode/templates/admin/users/users.html:86 -#: rhodecode/templates/base/base.html:79 -msgid "LDAP" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:28 -msgid "Connection settings" -msgstr "Options de connexion" - -#: rhodecode/templates/admin/ldap/ldap.html:30 -msgid "Enable LDAP" -msgstr "Activer le LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:34 -msgid "Host" -msgstr "Serveur" - -#: rhodecode/templates/admin/ldap/ldap.html:38 -msgid "Port" -msgstr "Port" - -#: rhodecode/templates/admin/ldap/ldap.html:42 -msgid "Account" -msgstr "Compte" - -#: rhodecode/templates/admin/ldap/ldap.html:50 -msgid "Connection security" -msgstr "Connexion sécurisée" - -#: rhodecode/templates/admin/ldap/ldap.html:54 -msgid "Certificate Checks" -msgstr "Vérif. des certificats" - -#: rhodecode/templates/admin/ldap/ldap.html:57 -msgid "Search settings" -msgstr "Réglages de recherche" - -#: rhodecode/templates/admin/ldap/ldap.html:59 -msgid "Base DN" -msgstr "Base de recherche" - -#: rhodecode/templates/admin/ldap/ldap.html:63 -msgid "LDAP Filter" -msgstr "Filtre de recherche" - -#: rhodecode/templates/admin/ldap/ldap.html:67 -msgid "LDAP Search Scope" -msgstr "Portée de recherche" - -#: rhodecode/templates/admin/ldap/ldap.html:70 -msgid "Attribute mappings" -msgstr "Correspondance des attributs" - -#: rhodecode/templates/admin/ldap/ldap.html:72 -msgid "Login Attribute" -msgstr "Attribut pour le nom d’utilisateur" - -#: rhodecode/templates/admin/ldap/ldap.html:76 -msgid "First Name Attribute" -msgstr "Attribut pour le prénom" - -#: rhodecode/templates/admin/ldap/ldap.html:80 -msgid "Last Name Attribute" -msgstr "Attribut pour le nom de famille" - -#: rhodecode/templates/admin/ldap/ldap.html:84 -msgid "E-mail Attribute" -msgstr "Attribut pour l’e-mail" - -#: rhodecode/templates/admin/notifications/notifications.html:5 -#: rhodecode/templates/admin/notifications/notifications.html:9 +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "Mon compte" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" +msgstr "Mon compte" + +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "Surveillé" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "Requêtes de pull" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "Mes permissions" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "Ajouter" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "Supprimer" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "Veuillez confirmer la suppression de l’e-mail : %s" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "Nouvelle adrese" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "Nouveau mot de passe" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "Vous pouvez changer votre avatar sur" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "en utilisant l’adresse" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "" +"Your user is in an external Source of Record; some details cannot be " +"managed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "Ouvertes par moi" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "Requête de pull nº%s ouverte le %s" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "Fermée" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "Veuillez confirmer la suppression de cette requête de pull." + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "Rien ici pour le moment" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "Je participe à" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "Requête de pull nº%s ouverte par %s le %s" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "Aucun élément n’a été trouvé." + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 msgid "My Notifications" msgstr "Mes notifications" -#: rhodecode/templates/admin/notifications/notifications.html:29 +#: kallithea/templates/admin/notifications/notifications.html:32 msgid "All" msgstr "Tous" -#: rhodecode/templates/admin/notifications/notifications.html:30 +#: kallithea/templates/admin/notifications/notifications.html:33 msgid "Comments" msgstr "Commentaires" -#: rhodecode/templates/admin/notifications/notifications.html:31 -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:8 -msgid "Pull requests" -msgstr "Requêtes de pull" - -#: rhodecode/templates/admin/notifications/notifications.html:35 +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:38 msgid "Mark all read" msgstr "Tout marquer comme lu" -#: rhodecode/templates/admin/notifications/notifications_data.html:39 +#: kallithea/templates/admin/notifications/notifications_data.html:40 msgid "No notifications here yet" msgstr "Aucune notification pour le moment." -#: rhodecode/templates/admin/notifications/show_notification.html:5 -#: rhodecode/templates/admin/notifications/show_notification.html:11 +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 msgid "Show notification" msgstr "Notification" -#: rhodecode/templates/admin/notifications/show_notification.html:9 -#: rhodecode/templates/base/base.html:253 +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 msgid "Notifications" msgstr "Notifications" -#: rhodecode/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:5 msgid "Permissions administration" msgstr "Gestion des permissions" -#: rhodecode/templates/admin/permissions/permissions.html:11 -#: rhodecode/templates/admin/repos/repo_edit.html:151 -#: rhodecode/templates/admin/repos/repo_edit.html:158 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:81 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:88 -#: rhodecode/templates/admin/users/user_edit.html:150 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:129 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:136 -#: rhodecode/templates/base/base.html:78 +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 msgid "Permissions" msgstr "Permissions" -#: rhodecode/templates/admin/permissions/permissions.html:24 -msgid "Default permissions" -msgstr "Permissions par défaut" - -#: rhodecode/templates/admin/permissions/permissions.html:31 +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 msgid "Anonymous access" msgstr "Accès anonyme" -#: rhodecode/templates/admin/permissions/permissions.html:49 +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without need to log in. Anonymous users use %s " +"user permissions" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 msgid "" "All default permissions on each repository will be reset to chosen " -"permission, note that all custom default permission on repositories will be " -"lost" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:50 -#: rhodecode/templates/admin/permissions/permissions.html:63 -#: rhodecode/templates/admin/permissions/permissions.html:77 +"permission, note that all custom default permission on repositories will " +"be lost" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 msgid "Overwrite existing settings" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:62 +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "Groupe de dépôt" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 msgid "" "All default permissions on each repository group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 msgid "User group" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:76 +#: kallithea/templates/admin/permissions/permissions_globals.html:53 msgid "" "All default permissions on each user group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:83 +#: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" msgstr "Création de dépôt" -#: rhodecode/templates/admin/permissions/permissions.html:91 +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "" +"Write permission to repository groups allows creating repositories inside" +" that group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 msgid "User group creation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:99 +#: kallithea/templates/admin/permissions/permissions_globals.html:85 msgid "Repository forking" msgstr "Fork de dépôt" -#: rhodecode/templates/admin/permissions/permissions.html:107 +#: kallithea/templates/admin/permissions/permissions_globals.html:93 msgid "Registration" msgstr "Enregistrement" -#: rhodecode/templates/admin/permissions/permissions.html:115 +#: kallithea/templates/admin/permissions/permissions_globals.html:101 msgid "External auth account activation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:133 -msgid "Default User Permissions" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:144 -#: rhodecode/templates/admin/users/user_edit.html:207 -msgid "Allowed IP addresses" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:158 -#: rhodecode/templates/admin/repos/repo_edit.html:340 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#: rhodecode/templates/admin/users/user_edit.html:175 -#: rhodecode/templates/admin/users/user_edit.html:220 -#: rhodecode/templates/admin/users_groups/users_groups.html:54 -#: rhodecode/templates/data_table/_dt_elements.html:122 -#: rhodecode/templates/data_table/_dt_elements.html:136 -msgid "delete" -msgstr "Supprimer" - -#: rhodecode/templates/admin/permissions/permissions.html:159 -#: rhodecode/templates/admin/users/user_edit.html:221 +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 #, python-format msgid "Confirm to delete this ip: %s" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:165 -#: rhodecode/templates/admin/users/user_edit.html:227 +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 msgid "All IP addresses are allowed" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:176 -#: rhodecode/templates/admin/users/user_edit.html:238 +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:184 -#: rhodecode/templates/admin/repos/repo_add_base.html:73 -#: rhodecode/templates/admin/repos/repo_edit.html:380 -#: rhodecode/templates/admin/users/user_edit.html:197 -#: rhodecode/templates/admin/users/user_edit.html:245 -msgid "Add" -msgstr "Ajouter" - -#: rhodecode/templates/admin/repos/repo_add.html:12 -#: rhodecode/templates/admin/repos/repo_add.html:16 -#: rhodecode/templates/base/base.html:74 rhodecode/templates/base/base.html:88 -#: rhodecode/templates/base/base.html:116 -#: rhodecode/templates/base/base.html:275 -msgid "Repositories" -msgstr "Dépôts" - -#: rhodecode/templates/admin/repos/repo_add.html:19 -msgid "Add new" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:20 -#: rhodecode/templates/summary/summary.html:96 -#: rhodecode/templates/summary/summary.html:97 -msgid "Clone from" -msgstr "Cloner depuis" - -#: rhodecode/templates/admin/repos/repo_add_base.html:24 -#: rhodecode/templates/admin/repos/repo_edit.html:45 -msgid "Optional http[s] url from which repository should be cloned." -msgstr "URL http(s) depuis laquelle le dépôt doit être cloné." - -#: rhodecode/templates/admin/repos/repo_add_base.html:33 -#: rhodecode/templates/forks/fork.html:51 -msgid "Optionaly select a group to put this repository into." -msgstr "Sélectionnez un groupe (optionel) dans lequel sera placé le dépôt." - -#: rhodecode/templates/admin/repos/repo_add_base.html:42 -msgid "Type of repository to create." -msgstr "Type de dépôt à créer." - -#: rhodecode/templates/admin/repos/repo_add_base.html:47 -#: rhodecode/templates/admin/repos/repo_edit.html:59 -#: rhodecode/templates/forks/fork.html:38 -msgid "Landing revision" -msgstr "Révision d’arrivée" - -#: rhodecode/templates/admin/repos/repo_add_base.html:51 -#: rhodecode/templates/admin/repos/repo_edit.html:63 -#: rhodecode/templates/forks/fork.html:42 -msgid "Default revision for files page, downloads, whoosh and readme" -msgstr "Révision par défaut pour les pages de fichiers, de téléchargements, de recherche et de documentation." - -#: rhodecode/templates/admin/repos/repo_add_base.html:60 -#: rhodecode/templates/admin/repos/repo_edit.html:72 -#: rhodecode/templates/forks/fork.html:60 -msgid "" -"Keep it short and to the point. Use a README file for longer descriptions." -msgstr "Gardez cette description précise et concise. Utilisez un fichier README pour des descriptions plus détaillées." - -#: rhodecode/templates/admin/repos/repo_edit.html:8 -msgid "Edit repository" -msgstr "Éditer le dépôt" - -#: rhodecode/templates/admin/repos/repo_edit.html:12 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:11 -#: rhodecode/templates/base/base.html:81 -#: rhodecode/templates/base/base.html:134 -#: rhodecode/templates/summary/summary.html:212 +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "Nom de groupe" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "Parent du groupe" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 msgid "Settings" msgstr "Options" -#: rhodecode/templates/admin/repos/repo_edit.html:36 -msgid "Non-changeable id" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:41 -msgid "Clone uri" -msgstr "URL de clone" - -#: rhodecode/templates/admin/repos/repo_edit.html:54 -msgid "Optional select a group to put this repository into." -msgstr "Sélectionnez un groupe (optionel) dans lequel sera placé le dépôt." - -#: rhodecode/templates/admin/repos/repo_edit.html:119 -msgid "Change owner of this repository." -msgstr "Changer le propriétaire de ce dépôt." - -#: rhodecode/templates/admin/repos/repo_edit.html:177 -msgid "Advanced settings" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:180 -msgid "Statistics" -msgstr "Statistiques" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Reset current statistics" -msgstr "Réinitialiser les statistiques" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Confirm to remove current statistics" -msgstr "Souhaitez-vous vraiment réinitialiser les statistiques de ce dépôt ?" - -#: rhodecode/templates/admin/repos/repo_edit.html:187 -msgid "Fetched to rev" -msgstr "Parcouru jusqu’à la révision" - -#: rhodecode/templates/admin/repos/repo_edit.html:188 -msgid "Stats gathered" -msgstr "Statistiques obtenues" - -#: rhodecode/templates/admin/repos/repo_edit.html:196 -msgid "Remote" -msgstr "Dépôt distant" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Pull changes from remote location" -msgstr "Récupérer les changements depuis le site distant" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Confirm to pull changes from remote side" -msgstr "Voulez-vous vraiment récupérer les changements depuis le site distant ?" - -#: rhodecode/templates/admin/repos/repo_edit.html:211 -msgid "Cache" -msgstr "Cache" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Invalidate repository cache" -msgstr "Invalider le cache du dépôt" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Confirm to invalidate repository cache" -msgstr "Voulez-vous vraiment invalider le cache du dépôt ?" - -#: rhodecode/templates/admin/repos/repo_edit.html:218 -msgid "" -"Manually invalidate cache for this repository. On first access repository " -"will be cached again" -msgstr "Invalide manuellement le cache de ce dépôt. Au prochain accès sur ce dépôt, il sera à nouveau mis en cache." - -#: rhodecode/templates/admin/repos/repo_edit.html:223 -msgid "List of cached values" -msgstr "Liste des valeurs en cache" - -#: rhodecode/templates/admin/repos/repo_edit.html:226 -msgid "Prefix" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:227 -msgid "Key" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:228 -#: rhodecode/templates/admin/users/user_add.html:86 -#: rhodecode/templates/admin/users/user_edit.html:124 -#: rhodecode/templates/admin/users/users.html:84 -#: rhodecode/templates/admin/users_groups/users_group_add.html:41 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 -#: rhodecode/templates/admin/users_groups/users_groups.html:39 -msgid "Active" -msgstr "Actif" - -#: rhodecode/templates/admin/repos/repo_edit.html:243 -#: rhodecode/templates/base/base.html:292 -#: rhodecode/templates/base/base.html:293 -msgid "Public journal" -msgstr "Journal public" - -#: rhodecode/templates/admin/repos/repo_edit.html:249 -msgid "Remove from public journal" -msgstr "Supprimer du journal public" - -#: rhodecode/templates/admin/repos/repo_edit.html:251 -msgid "Add to public journal" -msgstr "Ajouter le dépôt au journal public" - -#: rhodecode/templates/admin/repos/repo_edit.html:256 -msgid "" -"All actions made on this repository will be accessible to everyone in public" -" journal" -msgstr "Le descriptif des actions réalisées sur ce dépôt sera visible à tous depuis le journal public." - -#: rhodecode/templates/admin/repos/repo_edit.html:263 -msgid "Locking" -msgstr "Verrouillage" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Unlock locked repo" -msgstr "Déverrouiller le dépôt" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Confirm to unlock repository" -msgstr "Veuillez confirmer le déverrouillage de ce dépôt." - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Lock repo" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Confirm to lock repository" -msgstr "Veuillez confirmer le verrouillage de ce dépôt." - -#: rhodecode/templates/admin/repos/repo_edit.html:272 -msgid "Repository is not locked" -msgstr "Ce dépôt n’est pas verrouillé." - -#: rhodecode/templates/admin/repos/repo_edit.html:277 -msgid "" -"Force locking on repository. Works only when anonymous access is disabled" -msgstr "Forcer le verrouillage du dépôt. Ce réglage fonctionne uniquement quand l‘accès anonyme est désactivé." - -#: rhodecode/templates/admin/repos/repo_edit.html:284 -msgid "Set as fork of" -msgstr "Indiquer comme fork" - -#: rhodecode/templates/admin/repos/repo_edit.html:289 -msgid "Set" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:293 -msgid "Manually set this repository as a fork of another from the list" -msgstr "Marquer ce dépôt comme fork d’un autre dépôt de la liste." - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Remove this repository" -msgstr "Supprimer ce dépôt" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Confirm to delete this repository" -msgstr "Voulez-vous vraiment supprimer ce dépôt ?" - -#: rhodecode/templates/admin/repos/repo_edit.html:310 -#, python-format -msgid "this repository has %s fork" -msgid_plural "this repository has %s forks" -msgstr[0] "" -msgstr[1] "" - -#: rhodecode/templates/admin/repos/repo_edit.html:311 -msgid "Detach forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:312 -msgid "Delete forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:315 -msgid "" -"This repository will be renamed in a special way in order to be unaccesible " -"for RhodeCode and VCS systems. If you need to fully delete it from file " -"system please do it manually" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:329 -msgid "Extra fields" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:341 -#, python-format -msgid "Confirm to delete this field: %s" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:355 -msgid "New field key" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:363 -msgid "New field label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:366 -msgid "Enter short label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:372 -msgid "New field description" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:375 -msgid "Enter description of a field" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:3 -msgid "none" -msgstr "Aucune" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:4 -msgid "read" -msgstr "Lecture" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:5 -msgid "write" -msgstr "Écriture" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:6 -msgid "admin" -msgstr "Administration" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:7 -msgid "member" -msgstr "Membre" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:16 -msgid "private repository" -msgstr "Dépôt privé" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:19 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:28 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:20 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:35 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:20 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:35 -msgid "default" -msgstr "[Par défaut]" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:33 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:58 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:25 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:55 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:25 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:55 -msgid "revoke" -msgstr "Révoquer" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:83 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:81 -msgid "Add another member" -msgstr "Ajouter un utilisateur" - -#: rhodecode/templates/admin/repos/repos.html:5 -msgid "Repositories administration" -msgstr "Administration des dépôts" - -#: rhodecode/templates/admin/repos/repos.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account.html:185 -#: rhodecode/templates/admin/users/users.html:109 -#: rhodecode/templates/bookmarks/bookmarks.html:76 -#: rhodecode/templates/branches/branches.html:75 -#: rhodecode/templates/journal/journal.html:206 -#: rhodecode/templates/journal/journal.html:296 -#: rhodecode/templates/tags/tags.html:76 -msgid "No records found." -msgstr "Aucun élément n’a été trouvé." - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:87 -msgid "apply to children" -msgstr "Appliquer aux enfants" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:88 -msgid "" -"Set or revoke permission to all children of that group, including non-" -"private repositories and other groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:4 -#, python-format -msgid "%s Group Dashboard" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:9 -msgid "Home" -msgstr "Accueil" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:13 -msgid "with" -msgstr "comprenant" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5 -msgid "Add repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:16 -#: rhodecode/templates/base/base.html:75 rhodecode/templates/base/base.html:91 -msgid "Repository groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:13 -msgid "Add new repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:51 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:56 -msgid "Group parent" -msgstr "Parent du groupe" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:59 -msgid "save" -msgstr "Enregistrer" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5 -msgid "Edit repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:13 -#, python-format -msgid "Edit repository group %s" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:27 -msgid "Add child group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:68 -msgid "" -"Enable lock-by-pulling on group. This option will be applied to all other " -"groups and repositories inside" -msgstr "Activer le verrou lors d’un pull sur le groupe. Cette option sera appliquée à tous les sous-groupes et dépôts de ce groupe." - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5 -msgid "Repository groups administration" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:45 -msgid "Number of toplevel repositories" -msgstr "Nombre de sous-dépôts" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:64 -#: rhodecode/templates/admin/users_groups/users_groups.html:48 -#: rhodecode/templates/changeset/changeset_file_comment.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:171 -msgid "Edit" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:65 -#: rhodecode/templates/admin/users_groups/users_groups.html:49 -#: rhodecode/templates/base/perms_summary.html:29 -#: rhodecode/templates/base/perms_summary.html:60 -#: rhodecode/templates/base/perms_summary.html:62 -#: rhodecode/templates/data_table/_dt_elements.html:116 -#: rhodecode/templates/data_table/_dt_elements.html:117 -#: rhodecode/templates/data_table/_dt_elements.html:130 -#: rhodecode/templates/data_table/_dt_elements.html:131 -msgid "edit" -msgstr "éditer" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "Créé le" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 #, python-format msgid "Confirm to delete this group: %s with %s repository" msgid_plural "Confirm to delete this group: %s with %s repositories" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:78 -msgid "There are no repository groups yet" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:5 -#: rhodecode/templates/admin/settings/settings.html:5 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "Aucune" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "Lecture" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "Écriture" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "Administration" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "[Par défaut]" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "Révoquer" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "Appliquer aux enfants" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "" +"Set or revoke permission to all children of that group, including non-" +"private repositories and other groups if selected." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "" +"Enable lock-by-pulling on group. This option will be applied to all other" +" groups and repositories inside" +msgstr "" +"Activer le verrou lors d’un pull sur le groupe. Cette option sera " +"appliquée à tous les sous-groupes et dépôts de ce groupe." + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "%s Repository group dashboard" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "Accueil" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "comprenant" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "Nombre de sous-dépôts" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "Ajouter un dépôt" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "Cloner depuis" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "URL http(s) depuis laquelle le dépôt doit être cloné." + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "" +"Gardez cette description précise et concise. Utilisez un fichier README " +"pour des descriptions plus détaillées." + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "Sélectionnez un groupe (optionel) dans lequel sera placé le dépôt." + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "Type de dépôt à créer." + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "Révision d’arrivée" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is beeing created, you will be redirected " +"when this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:42 +msgid "" +"We're sorry but error occured during this operation. Please check your " +"Kallithea server logs, or contact administrator." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, python-format +msgid "%s repository settings" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +msgid "Remote" +msgstr "Dépôt distant" + +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "Statistiques" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "Fork de" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "Marquer ce dépôt comme fork d’un autre dépôt de la liste." + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Remove from public journal" +msgstr "Supprimer du journal public" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +msgid "Add to public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 +msgid "" +"All actions made on this repository will be accessible to everyone in " +"public journal" +msgstr "" +"Le descriptif des actions réalisées sur ce dépôt sera visible à tous " +"depuis le journal public." + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 +msgid "Confirm to unlock repository" +msgstr "Veuillez confirmer le déverrouillage de ce dépôt." + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 +msgid "Confirm to lock repository" +msgstr "Veuillez confirmer le verrouillage de ce dépôt." + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 +msgid "Repository is not locked" +msgstr "Ce dépôt n’est pas verrouillé." + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 +msgid "" +"Force locking on repository. Works only when anonymous access is " +"disabled. Trigering a pull locks repository by user who pulled, only the " +"same user can unlock by doing a push" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "Voulez-vous vraiment supprimer le dépôt %s ?" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +msgid "Delete this repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 +#, python-format +msgid "this repository has %s fork" +msgid_plural "this repository has %s forks" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 +msgid "Detach forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 +msgid "Delete forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "" +"This repository will be renamed in a special way in order to be " +"unaccesible for Kallithea and VCS systems. If you need to fully delete it" +" from file system please do it manually" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "Invalider le cache du dépôt" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "Voulez-vous vraiment invalider le cache du dépôt ?" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 +msgid "" +"Manually invalidate cache for this repository. On first access repository" +" will be cached again" +msgstr "" +"Invalide manuellement le cache de ce dépôt. Au prochain accès sur ce " +"dépôt, il sera à nouveau mis en cache." + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "Liste des valeurs en cache" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "Actif" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#, python-format +msgid "Confirm to delete this field: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 +msgid "New field key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 +msgid "New field label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 +msgid "Enter short label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 +msgid "New field description" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +msgid "Enter description of a field" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 +msgid "private repository" +msgstr "Dépôt privé" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "Récupérer les changements depuis le site distant" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "Voulez-vous vraiment récupérer les changements depuis le site distant ?" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 +msgid "" +"In case this repository is renamed or moved into another group the " +"repository url changes.\n" +" Using above url guarantees that this " +"repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases" +" that you need to hardcode the url into 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "URL de clone" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "éditer" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "Sélectionnez un groupe (optionel) dans lequel sera placé le dépôt." + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "" +"Révision par défaut pour les pages de fichiers, de téléchargements, de " +"recherche et de documentation." + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "Changer le propriétaire de ce dépôt." + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "Souhaitez-vous vraiment réinitialiser les statistiques de ce dépôt ?" + +#: kallithea/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "Administration des dépôts" + +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 msgid "Settings administration" msgstr "Administration générale" -#: rhodecode/templates/admin/settings/hooks.html:24 -msgid "Built in hooks - read only" -msgstr "Hooks prédéfinis (lecture seule)" - -#: rhodecode/templates/admin/settings/hooks.html:40 +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "Hooks" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:16 +msgid "SMTP auth" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:39 +msgid "Send" +msgstr "Envoyer" + +#: kallithea/templates/admin/settings/settings_global.html:8 +msgid "Site branding" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:18 +msgid "HTTP authentication realm" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:27 +msgid "Google Analytics code" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:50 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 +msgid "Save settings" +msgstr "Enregister les options" + +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "" +"Hooks can be used to trigger actions on certain events such as push / " +"pull. They can trigger Python functions or external applications." +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 msgid "Custom hooks" msgstr "Hooks personnalisés" -#: rhodecode/templates/admin/settings/hooks.html:56 -msgid "remove" -msgstr "Enlever" - -#: rhodecode/templates/admin/settings/hooks.html:88 +#: kallithea/templates/admin/settings/settings_hooks.html:69 msgid "Failed to remove hook" msgstr "Erreur lors de la suppression du hook." -#: rhodecode/templates/admin/settings/settings.html:26 -msgid "Remap and rescan repositories" -msgstr "Ré-associer et re-scanner les dépôts" - -#: rhodecode/templates/admin/settings/settings.html:34 +#: kallithea/templates/admin/settings/settings_mapping.html:6 msgid "Rescan option" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:40 +#: kallithea/templates/admin/settings/settings_mapping.html:11 +msgid "Destroy old data" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:13 msgid "" -"In case a repository was deleted from filesystem and there are leftovers in " -"the database check this option to scan obsolete data in database and remove " -"it." -msgstr "Cochez cette option pour supprimer d’éventuelles données obsolètes (concernant des dépôts manuellement supprimés) de la base de données." - -#: rhodecode/templates/admin/settings/settings.html:41 -msgid "Destroy old data" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:43 +"In case a repository was deleted from filesystem and it still exists in " +"the database check this option to scan obsolete data in database and " +"remove it." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 msgid "" -"Rescan repositories location for new repositories. Also deletes obsolete if " -"`destroy` flag is checked " -msgstr "Rescanner le dossier contenant les dépôts pour en trouver de nouveaux. Supprime égalements les entrées de dépôts obsolètes si « Supprimer les données obsolètes » est coché." - -#: rhodecode/templates/admin/settings/settings.html:48 -msgid "Rescan repositories" -msgstr "Re-scanner les dépôts" - -#: rhodecode/templates/admin/settings/settings.html:54 -msgid "Whoosh indexing" -msgstr "Indexation Whoosh" - -#: rhodecode/templates/admin/settings/settings.html:62 +"Each cache data for repositories will be cleaned with this option " +"selected. Use this to reload data and clear cache keys." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 +msgid "" +"Verify if Kallitheas GIT hooks are installed for each repository. Current" +" hooks will be updated to latest version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:7 msgid "Index build option" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:67 +#: kallithea/templates/admin/settings/settings_search.html:12 msgid "Build from scratch" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:73 +#: kallithea/templates/admin/settings/settings_search.html:15 +msgid "" +"This option completely reindex all the files within Kallithea for proper " +"fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:21 msgid "Reindex" msgstr "Mettre à jour l’index" -#: rhodecode/templates/admin/settings/settings.html:79 -msgid "Global application settings" -msgstr "Réglages d’application globaux" - -#: rhodecode/templates/admin/settings/settings.html:88 -msgid "Site branding" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:97 -msgid "HTTP authentication realm" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:106 -msgid "Google Analytics code" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:114 -#: rhodecode/templates/admin/settings/settings.html:195 -#: rhodecode/templates/admin/settings/settings.html:287 -msgid "Save settings" -msgstr "Enregister les options" - -#: rhodecode/templates/admin/settings/settings.html:121 -msgid "Visualisation settings" -msgstr "Réglages d’affichage" - -#: rhodecode/templates/admin/settings/settings.html:129 +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 +msgid "Web" +msgstr "Web" + +#: kallithea/templates/admin/settings/settings_vcs.html:11 +msgid "Require SSL for vcs operations" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:13 +msgid "" +"Activate to set Kallithea to require SSL for pushing or pulling. If SSL " +"certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 +msgid "Show repository size after push" +msgstr "Afficher la taille du dépôt après un push" + +#: kallithea/templates/admin/settings/settings_vcs.html:28 +msgid "Log user push commands" +msgstr "Journaliser les commandes de push" + +#: kallithea/templates/admin/settings/settings_vcs.html:32 +msgid "Log user pull commands" +msgstr "Journaliser les commandes de pull" + +#: kallithea/templates/admin/settings/settings_vcs.html:36 +msgid "Update repository after push (hg update)" +msgstr "Mettre à jour les dépôts après un push (hg update)" + +#: kallithea/templates/admin/settings/settings_vcs.html:42 +msgid "Mercurial Extensions" +msgstr "Extensions Mercurial" + +#: kallithea/templates/admin/settings/settings_vcs.html:47 +msgid "Enable largefiles extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:51 +msgid "Enable hgsubversion extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:53 +msgid "" +"Requires hgsubversion library to be installed. Allows cloning remote SVN " +"repositories and migrates them to Mercurial type." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 +msgid "Repositories location" +msgstr "Emplacement des dépôts" + +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting" +" take effect." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:72 +msgid "" +"Filesystem location where repositories should be stored. After changing " +"this value a restart and rescan of the repository folder are required." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:8 msgid "General" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:134 +#: kallithea/templates/admin/settings/settings_visual.html:13 msgid "Use repository extra fields" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:136 +#: kallithea/templates/admin/settings/settings_visual.html:15 msgid "Allows storing additional customized fields per repository." msgstr "" -#: rhodecode/templates/admin/settings/settings.html:139 -msgid "Show RhodeCode version" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:141 -msgid "Shows or hides displayed version of RhodeCode in the footer" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:146 +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:30 +msgid "" +"Gravatar url allows you to use other avatar server application.\n" +" Following " +"variables of the URL will be replaced accordingly.\n" +" {scheme} " +"'http' or 'https' sent from running Kallithea server,\n" +" {email} user " +"email,\n" +" {md5email} md5 " +"hash of the user email (like at gravatar.com),\n" +" {size} size " +"of the image that is expected from the server application,\n" +" {netloc} " +"network location/server host of running Kallithea server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:42 +msgid "" +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}'," +" available vars:\n" +" {scheme} 'http' " +"or 'https' sent from running Kallithea server,\n" +" {user} current " +"user username,\n" +" {netloc} network " +"location/server host of running Kallithea server,\n" +" {repo} full " +"repository name,\n" +" {repoid} ID of " +"repository, can be used to contruct clone-by-id" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:54 msgid "Dashboard items" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:150 +#: kallithea/templates/admin/settings/settings_visual.html:58 msgid "" -"Number of items displayed in lightweight dashboard before pagination is " +"Number of items displayed in the main page dashboard before pagination is" +" shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:68 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: rhodecode/templates/admin/settings/settings.html:155 +#: kallithea/templates/admin/settings/settings_visual.html:74 msgid "Icons" msgstr "Icônes" -#: rhodecode/templates/admin/settings/settings.html:160 +#: kallithea/templates/admin/settings/settings_visual.html:79 msgid "Show public repo icon on repositories" msgstr "Afficher l’icône de dépôt public sur les dépôts" -#: rhodecode/templates/admin/settings/settings.html:164 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Show private repo icon on repositories" msgstr "Afficher l’icône de dépôt privé sur les dépôts" -#: rhodecode/templates/admin/settings/settings.html:166 -msgid "Show public/private icons next to repositories names" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:172 +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:91 msgid "Meta-Tagging" msgstr "Meta-Tagging" -#: rhodecode/templates/admin/settings/settings.html:177 -msgid "Stylify recognised metatags:" -msgstr "Styliser les méta-tags reconnus :" - -#: rhodecode/templates/admin/settings/settings.html:204 -msgid "VCS settings" -msgstr "Réglages de gestionnaire de version" - -#: rhodecode/templates/admin/settings/settings.html:213 -msgid "Web" -msgstr "Web" - -#: rhodecode/templates/admin/settings/settings.html:218 -msgid "Require SSL for vcs operations" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:220 +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:110 msgid "" -"RhodeCode will require SSL for pushing or pulling. If SSL is missing it will" -" return HTTP Error 406: Not Acceptable" -msgstr "RhodeCode requièrera SSL pour les pushs et pulls. Si le SSL n’est pas utilisé l’erreur HTTP 406 (Non Acceptable) sera renvoyée." - -#: rhodecode/templates/admin/settings/settings.html:226 -msgid "Hooks" -msgstr "Hooks" - -#: rhodecode/templates/admin/settings/settings.html:231 -msgid "Update repository after push (hg update)" -msgstr "Mettre à jour les dépôts après un push (hg update)" - -#: rhodecode/templates/admin/settings/settings.html:235 -msgid "Show repository size after push" -msgstr "Afficher la taille du dépôt après un push" - -#: rhodecode/templates/admin/settings/settings.html:239 -msgid "Log user push commands" -msgstr "Journaliser les commandes de push" - -#: rhodecode/templates/admin/settings/settings.html:243 -msgid "Log user pull commands" -msgstr "Journaliser les commandes de pull" - -#: rhodecode/templates/admin/settings/settings.html:247 -msgid "Advanced setup" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:252 -msgid "Mercurial Extensions" -msgstr "Extensions Mercurial" - -#: rhodecode/templates/admin/settings/settings.html:257 -msgid "Enable largefiles extension" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:261 -msgid "Enable hgsubversion extension" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:263 -msgid "" -"Requires hgsubversion library installed. Allows cloning from svn remote " -"locations" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:274 -msgid "Repositories location" -msgstr "Emplacement des dépôts" - -#: rhodecode/templates/admin/settings/settings.html:279 -msgid "" -"Click to unlock. You must restart RhodeCode in order to make this setting " -"take effect." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:280 -#: rhodecode/templates/base/base.html:143 -msgid "Unlock" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:282 -msgid "" -"Location where repositories are stored. After changing this value a restart," -" and rescan is required" -msgstr "Emplacement de stockage des dépôts. Si cette valeur est changée, Rhodecode devra être redémarré les les dépôts rescannés." - -#: rhodecode/templates/admin/settings/settings.html:303 -msgid "Test Email" -msgstr "E-mail de test" - -#: rhodecode/templates/admin/settings/settings.html:311 -msgid "Email to" -msgstr "Envoyer l’e-mail à" - -#: rhodecode/templates/admin/settings/settings.html:319 -msgid "Send" -msgstr "Envoyer" - -#: rhodecode/templates/admin/settings/settings.html:325 -msgid "System Info and Packages" -msgstr "Information système et paquets" - -#: rhodecode/templates/admin/settings/settings.html:328 -#: rhodecode/templates/changelog/changelog.html:51 -msgid "Show" -msgstr "Afficher" - -#: rhodecode/templates/admin/users/user_add.html:5 +"Parses meta tags from repository description field and turns them into " +"colored tags." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 +msgid "Add user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 +msgid "User groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 +#, python-format +msgid "%s user group settings" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "Permissions par défaut" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 +msgid "Members" +msgstr "Membres" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 +#, python-format +msgid "User Group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 +#, python-format +msgid "Confirm to delete this user group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "Tout enlever" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "Membres disponibles" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "Tout ajouter" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 msgid "Add user" msgstr "Ajouter un utilisateur" -#: rhodecode/templates/admin/users/user_add.html:10 -#: rhodecode/templates/admin/users/user_edit.html:11 -#: rhodecode/templates/base/base.html:76 +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 msgid "Users" msgstr "Utilisateurs" -#: rhodecode/templates/admin/users/user_add.html:12 -#: rhodecode/templates/admin/users/users.html:23 -msgid "Add new user" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:50 +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:53 msgid "Password confirmation" msgstr "Confirmation" -#: rhodecode/templates/admin/users/user_edit.html:5 -msgid "Edit user" -msgstr "Éditer l'utilisateur" - -#: rhodecode/templates/admin/users/user_edit.html:13 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 -#, python-format -msgid "Edit %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:34 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:10 -msgid "Change your avatar at" -msgstr "Vous pouvez changer votre avatar sur" - -#: rhodecode/templates/admin/users/user_edit.html:35 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:11 -msgid "Using" -msgstr "en utilisant l’adresse" - -#: rhodecode/templates/admin/users/user_edit.html:43 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:20 -msgid "API key" -msgstr "Clé d’API" - -#: rhodecode/templates/admin/users/user_edit.html:50 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:25 -msgid "Current IP" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:70 -msgid "LDAP DN" -msgstr "DN LDAP" - -#: rhodecode/templates/admin/users/user_edit.html:79 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:44 -msgid "New password" -msgstr "Nouveau mot de passe" - -#: rhodecode/templates/admin/users/user_edit.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:53 +#: kallithea/templates/admin/users/user_edit.html:5 +#, python-format +msgid "%s user settings" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "Voulez-vous vraiment supprimer l’utilisateur « %s » ?" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 +#, python-format +msgid "" +"This user is in an external Source of Record (%s); some details cannot be" +" managed here." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 msgid "New password confirmation" msgstr "Confirmation du nouveau mot de passe" -#: rhodecode/templates/admin/users/user_edit.html:163 -msgid "Email addresses" -msgstr "Adresses e-mail" - -#: rhodecode/templates/admin/users/user_edit.html:176 -#, python-format -msgid "Confirm to delete this email: %s" -msgstr "Veuillez confirmer la suppression de l’e-mail : %s" - -#: rhodecode/templates/admin/users/user_edit.html:190 -msgid "New email address" -msgstr "Nouvelle adrese" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:5 -#: rhodecode/templates/base/base.html:254 -msgid "My account" -msgstr "Mon compte" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:9 -msgid "My Account" -msgstr "Mon compte" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:35 -msgid "My permissions" -msgstr "Mes permissions" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:38 -#: rhodecode/templates/journal/journal.html:54 -msgid "My repos" -msgstr "Mes dépôts" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:41 -msgid "My pull requests" -msgstr "Mes requêtes de pull" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:4 -msgid "Show closed pull requests" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:6 -msgid "Opened by me" -msgstr "Ouvertes par moi" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "Requête de pull nº%s ouverte le %s" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:17 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:45 -#: rhodecode/templates/pullrequests/pullrequest_data.html:11 -#: rhodecode/templates/pullrequests/pullrequest_show.html:27 -#: rhodecode/templates/pullrequests/pullrequest_show.html:42 -msgid "Closed" -msgstr "Fermée" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:23 -msgid "Confirm to delete this pull request" -msgstr "Veuillez confirmer la suppression de cette requête de pull." - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:30 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:51 -msgid "Nothing here yet" -msgstr "Rien ici pour le moment" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:34 -msgid "I participate in" -msgstr "Je participe à" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:42 -#: rhodecode/templates/pullrequests/pullrequest_data.html:8 -#, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "Requête de pull nº%s ouverte par %s le %s" - -#: rhodecode/templates/admin/users/users.html:5 +#: kallithea/templates/admin/users/users.html:5 msgid "Users administration" msgstr "Administration des utilisateurs" -#: rhodecode/templates/admin/users/users.html:9 +#: kallithea/templates/admin/users/users.html:13 msgid "users" msgstr "Utilisateurs" -#: rhodecode/templates/admin/users/users.html:80 +#: kallithea/templates/admin/users/users.html:54 msgid "Firstname" msgstr "" -#: rhodecode/templates/admin/users/users.html:81 +#: kallithea/templates/admin/users/users.html:55 msgid "Lastname" msgstr "" -#: rhodecode/templates/admin/users/users.html:82 +#: kallithea/templates/admin/users/users.html:56 msgid "Last login" msgstr "" -#: rhodecode/templates/admin/users_groups/users_group_add.html:5 -msgid "Add user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:10 -#: rhodecode/templates/admin/users_groups/users_groups.html:11 -#: rhodecode/templates/base/base.html:77 rhodecode/templates/base/base.html:94 -msgid "User groups" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:12 -#: rhodecode/templates/admin/users_groups/users_groups.html:26 -msgid "Add new user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 -msgid "Edit user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 -msgid "UserGroups" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 -#: rhodecode/templates/admin/users_groups/users_groups.html:38 -msgid "Members" -msgstr "Membres" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 -msgid "Chosen group members" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 -msgid "Remove all elements" -msgstr "Tout enlever" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 -msgid "Available members" -msgstr "Membres disponibles" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 -msgid "Add all elements" -msgstr "Tout ajouter" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:109 -msgid "No members yet" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:117 -msgid "Global Permissions" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:5 -msgid "User groups administration" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:55 -#, python-format -msgid "Confirm to delete this user group: %s" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:62 -msgid "There are no user groups yet" -msgstr "" - -#: rhodecode/templates/base/base.html:42 +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "" + +#: kallithea/templates/base/base.html:37 #, python-format msgid "Server instance: %s" msgstr "" -#: rhodecode/templates/base/base.html:52 -msgid "Report a bug" -msgstr "" - -#: rhodecode/templates/base/base.html:121 -#: rhodecode/templates/data_table/_dt_elements.html:9 -#: rhodecode/templates/data_table/_dt_elements.html:11 -#: rhodecode/templates/data_table/_dt_elements.html:13 -#: rhodecode/templates/summary/summary.html:8 +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 msgid "Summary" msgstr "Résumé" -#: rhodecode/templates/base/base.html:122 -#: rhodecode/templates/changelog/changelog.html:15 -#: rhodecode/templates/data_table/_dt_elements.html:17 -#: rhodecode/templates/data_table/_dt_elements.html:19 -#: rhodecode/templates/data_table/_dt_elements.html:21 +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 msgid "Changelog" msgstr "Historique" -#: rhodecode/templates/base/base.html:123 -#: rhodecode/templates/data_table/_dt_elements.html:25 -#: rhodecode/templates/data_table/_dt_elements.html:27 -#: rhodecode/templates/data_table/_dt_elements.html:29 -#: rhodecode/templates/files/files.html:12 +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 msgid "Files" msgstr "Fichiers" -#: rhodecode/templates/base/base.html:125 +#: kallithea/templates/base/base.html:149 msgid "Switch To" msgstr "" -#: rhodecode/templates/base/base.html:127 -#: rhodecode/templates/base/base.html:279 -msgid "loading..." -msgstr "Chargement…" - -#: rhodecode/templates/base/base.html:131 +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 msgid "Options" msgstr "Options" -#: rhodecode/templates/base/base.html:137 -#: rhodecode/templates/forks/forks_data.html:21 +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 msgid "Compare fork" msgstr "Comparer le fork" -#: rhodecode/templates/base/base.html:139 -#: rhodecode/templates/base/base.html:312 -#: rhodecode/templates/search/search.html:14 -#: rhodecode/templates/search/search.html:54 +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "Comparer" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 msgid "Search" msgstr "Rechercher" -#: rhodecode/templates/base/base.html:145 +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "" + +#: kallithea/templates/base/base.html:176 msgid "Lock" msgstr "" -#: rhodecode/templates/base/base.html:153 +#: kallithea/templates/base/base.html:184 msgid "Follow" msgstr "" -#: rhodecode/templates/base/base.html:154 +#: kallithea/templates/base/base.html:185 msgid "Unfollow" msgstr "" -#: rhodecode/templates/base/base.html:157 -#: rhodecode/templates/data_table/_dt_elements.html:33 -#: rhodecode/templates/data_table/_dt_elements.html:35 -#: rhodecode/templates/data_table/_dt_elements.html:37 -#: rhodecode/templates/data_table/_dt_elements.html:74 -#: rhodecode/templates/forks/fork.html:9 +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 msgid "Fork" msgstr "Fork" -#: rhodecode/templates/base/base.html:159 +#: kallithea/templates/base/base.html:190 msgid "Create Pull Request" msgstr "" -#: rhodecode/templates/base/base.html:165 -msgid "Show Pull Requests" -msgstr "" - -#: rhodecode/templates/base/base.html:165 -msgid "Pull Requests" -msgstr "" - -#: rhodecode/templates/base/base.html:202 +#: kallithea/templates/base/base.html:196 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "" + +#: kallithea/templates/base/base.html:233 msgid "Not logged in" msgstr "" -#: rhodecode/templates/base/base.html:209 +#: kallithea/templates/base/base.html:240 msgid "Login to your account" msgstr "Connexion à votre compte" -#: rhodecode/templates/base/base.html:232 +#: kallithea/templates/base/base.html:263 msgid "Forgot password ?" msgstr "Mot de passe oublié ?" -#: rhodecode/templates/base/base.html:255 +#: kallithea/templates/base/base.html:286 msgid "Log Out" msgstr "Se déconnecter" -#: rhodecode/templates/base/base.html:274 -msgid "Switch repository" -msgstr "Aller au dépôt" - -#: rhodecode/templates/base/base.html:286 +#: kallithea/templates/base/base.html:311 msgid "Show recent activity" msgstr "" -#: rhodecode/templates/base/base.html:287 -#: rhodecode/templates/journal/journal.html:4 +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 msgid "Journal" msgstr "Historique" -#: rhodecode/templates/base/base.html:298 +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "Journal public" + +#: kallithea/templates/base/base.html:323 msgid "Show public gists" msgstr "" -#: rhodecode/templates/base/base.html:303 +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "" + +#: kallithea/templates/base/base.html:328 msgid "All public gists" msgstr "" -#: rhodecode/templates/base/base.html:305 +#: kallithea/templates/base/base.html:330 msgid "My public gists" msgstr "" -#: rhodecode/templates/base/base.html:306 +#: kallithea/templates/base/base.html:331 msgid "My private gists" msgstr "" -#: rhodecode/templates/base/base.html:311 +#: kallithea/templates/base/base.html:336 msgid "Search in repositories" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:14 -msgid "Inherit default permissions" -msgstr "Utiliser les permissions par défaut" - -#: rhodecode/templates/base/default_perms_box.html:18 +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:19 #, python-format msgid "" -"Select to inherit permissions from %s settings. With this selected below " -"options does not apply." -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:26 +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:28 msgid "Create repositories" msgstr "Création de dépôts" -#: rhodecode/templates/base/default_perms_box.html:30 +#: kallithea/templates/base/default_perms_box.html:33 msgid "Select this option to allow repository creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:35 +#: kallithea/templates/base/default_perms_box.html:40 msgid "Create user groups" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:39 +#: kallithea/templates/base/default_perms_box.html:45 msgid "Select this option to allow user group creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:44 +#: kallithea/templates/base/default_perms_box.html:52 msgid "Fork repositories" msgstr "Forker les dépôts" -#: rhodecode/templates/base/default_perms_box.html:48 +#: kallithea/templates/base/default_perms_box.html:57 msgid "Select this option to allow repository forking for this user" msgstr "" -#: rhodecode/templates/base/perms_summary.html:11 +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:22 msgid "No permissions defined yet" msgstr "" -#: rhodecode/templates/base/perms_summary.html:19 -#: rhodecode/templates/base/perms_summary.html:38 +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 msgid "Permission" msgstr "Permission" -#: rhodecode/templates/base/perms_summary.html:20 -#: rhodecode/templates/base/perms_summary.html:39 +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 msgid "Edit Permission" msgstr "Éditer" -#: rhodecode/templates/base/root.html:44 +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 msgid "Add another comment" msgstr "" -#: rhodecode/templates/base/root.html:45 -#: rhodecode/templates/data_table/_dt_elements.html:147 +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 msgid "Stop following this repository" msgstr "Arrêter de suivre ce dépôt" -#: rhodecode/templates/base/root.html:46 +#: kallithea/templates/base/root.html:47 msgid "Start following this repository" msgstr "Suivre ce dépôt" -#: rhodecode/templates/base/root.html:47 +#: kallithea/templates/base/root.html:48 msgid "Group" msgstr "Groupe" -#: rhodecode/templates/base/root.html:48 +#: kallithea/templates/base/root.html:49 msgid "members" msgstr "Membres" -#: rhodecode/templates/base/root.html:49 -#: rhodecode/templates/pullrequests/pullrequest.html:203 +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 msgid "Loading ..." msgstr "" -#: rhodecode/templates/base/root.html:50 +#: kallithea/templates/base/root.html:51 +msgid "loading ..." +msgstr "" + +#: kallithea/templates/base/root.html:52 msgid "Search truncated" msgstr "" -#: rhodecode/templates/base/root.html:51 +#: kallithea/templates/base/root.html:53 msgid "No matching files" msgstr "" -#: rhodecode/templates/base/root.html:52 -#: rhodecode/templates/changelog/changelog.html:45 +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 msgid "Open new pull request" msgstr "Nouvelle requête de pull" -#: rhodecode/templates/base/root.html:53 +#: kallithea/templates/base/root.html:55 msgid "Open new pull request for selected changesets" msgstr "" -#: rhodecode/templates/base/root.html:54 +#: kallithea/templates/base/root.html:56 msgid "Show selected changesets __S -> __E" msgstr "" -#: rhodecode/templates/base/root.html:55 +#: kallithea/templates/base/root.html:57 msgid "Show selected changeset __S" msgstr "" -#: rhodecode/templates/base/root.html:56 +#: kallithea/templates/base/root.html:58 msgid "Selection link" msgstr "Lien vers la sélection" -#: rhodecode/templates/base/root.html:57 -#: rhodecode/templates/changeset/diff_block.html:8 +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 msgid "Collapse diff" msgstr "" -#: rhodecode/templates/base/root.html:58 +#: kallithea/templates/base/root.html:60 msgid "Expand diff" msgstr "" -#: rhodecode/templates/base/root.html:59 +#: kallithea/templates/base/root.html:61 msgid "Failed to revoke permission" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:5 +#: kallithea/templates/base/root.html:62 +msgid "confirm to revoke permission for {0}: {1} ?" +msgstr "" + +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:5 #, python-format msgid "%s Bookmarks" msgstr "Signets de %s" -#: rhodecode/templates/bookmarks/bookmarks.html:26 -msgid "Compare bookmarks" -msgstr "" - -#: rhodecode/templates/bookmarks/bookmarks.html:51 -#: rhodecode/templates/bookmarks/bookmarks_data.html:8 -#: rhodecode/templates/branches/branches.html:50 -#: rhodecode/templates/branches/branches_data.html:8 -#: rhodecode/templates/changelog/changelog_summary_data.html:8 -#: rhodecode/templates/tags/tags.html:51 -#: rhodecode/templates/tags/tags_data.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 msgid "Author" msgstr "Auteur" -#: rhodecode/templates/bookmarks/bookmarks.html:52 -#: rhodecode/templates/bookmarks/bookmarks_data.html:9 -#: rhodecode/templates/branches/branches.html:51 -#: rhodecode/templates/branches/branches_data.html:9 -#: rhodecode/templates/changelog/changelog_summary_data.html:5 -#: rhodecode/templates/tags/tags.html:52 -#: rhodecode/templates/tags/tags_data.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 msgid "Revision" msgstr "Révision" -#: rhodecode/templates/bookmarks/bookmarks.html:54 -#: rhodecode/templates/bookmarks/bookmarks_data.html:10 -#: rhodecode/templates/branches/branches.html:53 -#: rhodecode/templates/branches/branches_data.html:10 -#: rhodecode/templates/tags/tags.html:54 -#: rhodecode/templates/tags/tags_data.html:10 -msgid "Compare" -msgstr "Comparer" - -#: rhodecode/templates/branches/branches.html:5 +#: kallithea/templates/branches/branches.html:5 #, python-format msgid "%s Branches" msgstr "Branches de %s" -#: rhodecode/templates/branches/branches.html:26 -msgid "Compare branches" -msgstr "Comparer les branches" - -#: rhodecode/templates/changelog/changelog.html:6 +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 #, python-format msgid "%s Changelog" msgstr "Historique de %s" -#: rhodecode/templates/changelog/changelog.html:19 +#: kallithea/templates/changelog/changelog.html:21 #, python-format msgid "showing %d out of %d revision" msgid_plural "showing %d out of %d revisions" msgstr[0] "Affichage de %d révision sur %d" msgstr[1] "Affichage de %d révisions sur %d" -#: rhodecode/templates/changelog/changelog.html:39 +#: kallithea/templates/changelog/changelog.html:43 msgid "Clear selection" msgstr "" -#: rhodecode/templates/changelog/changelog.html:42 -#: rhodecode/templates/forks/forks_data.html:19 +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 #, python-format msgid "Compare fork with %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:42 -msgid "Compare fork with parent" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:78 -#: rhodecode/templates/changelog/changelog_summary_data.html:28 -#, python-format -msgid "Click to open associated pull request #%s" -msgstr "Cliquez ici pour ouvrir la requête de pull associée #%s." - -#: rhodecode/templates/changelog/changelog.html:102 -#: rhodecode/templates/summary/summary.html:403 -msgid "Show more" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:115 -#: rhodecode/templates/changelog/changelog_summary_data.html:50 -#: rhodecode/templates/changeset/changeset.html:107 -#: rhodecode/templates/changeset/changeset_range.html:86 +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "Afficher" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 +#, python-format +msgid "" +"Changeset status: %s\n" +"Click to open associated pull request #%s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 +#, python-format +msgid "Changeset status: %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:114 +msgid "Changeset has comments" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 #, python-format msgid "Bookmark %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:121 -#: rhodecode/templates/changelog/changelog_summary_data.html:56 -#: rhodecode/templates/changeset/changeset.html:113 -#: rhodecode/templates/changeset/changeset_range.html:92 +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 #, python-format msgid "Tag %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:126 -#: rhodecode/templates/changelog/changelog_summary_data.html:61 -#: rhodecode/templates/changeset/changeset.html:117 -#: rhodecode/templates/changeset/changeset_range.html:96 +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 #, python-format msgid "Branch %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:286 +#: kallithea/templates/changelog/changelog.html:299 msgid "There are no changes yet" msgstr "Il n’y a aucun changement pour le moment" -#: rhodecode/templates/changelog/changelog_details.html:4 -#: rhodecode/templates/changeset/changeset.html:91 +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 msgid "Removed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:5 -#: rhodecode/templates/changeset/changeset.html:92 +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 msgid "Changed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:6 -#: rhodecode/templates/changeset/changeset.html:93 +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 msgid "Added" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:8 -#: rhodecode/templates/changelog/changelog_details.html:9 -#: rhodecode/templates/changelog/changelog_details.html:10 -#: rhodecode/templates/changeset/changeset.html:95 -#: rhodecode/templates/changeset/changeset.html:96 -#: rhodecode/templates/changeset/changeset.html:97 +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 #, python-format msgid "Affected %s files" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:6 -#: rhodecode/templates/files/files_add.html:75 -#: rhodecode/templates/files/files_edit.html:61 +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 msgid "Commit message" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/changelog/changelog_summary_data.html:7 msgid "Age" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/changelog/changelog_summary_data.html:9 msgid "Refs" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:86 -msgid "Add or upload files directly via RhodeCode" -msgstr "Ajouter ou téléverser des fichiers directement via RhodeCode…" - -#: rhodecode/templates/changelog/changelog_summary_data.html:89 -#: rhodecode/templates/files/files_add.html:38 -#: rhodecode/templates/files/files_browser.html:31 -msgid "Add new file" -msgstr "Ajouter un nouveau fichier" - -#: rhodecode/templates/changelog/changelog_summary_data.html:95 +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" +msgstr "Ajouter ou téléverser des fichiers directement via Kallithea…" + +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:95 msgid "Push new repo" msgstr "Pusher le nouveau dépôt" -#: rhodecode/templates/changelog/changelog_summary_data.html:103 +#: kallithea/templates/changelog/changelog_summary_data.html:103 msgid "Existing repository?" msgstr "Le dépôt existe déjà ?" -#: rhodecode/templates/changeset/changeset.html:6 +#: kallithea/templates/changeset/changeset.html:6 #, python-format msgid "%s Changeset" msgstr "Changeset de %s" -#: rhodecode/templates/changeset/changeset.html:39 -msgid "No parents" -msgstr "Aucun parent" - -#: rhodecode/templates/changeset/changeset.html:49 -msgid "No children" -msgstr "" - -#: rhodecode/templates/changeset/changeset.html:62 -#: rhodecode/templates/changeset/changeset_file_comment.html:20 -#: rhodecode/templates/changeset/changeset_range.html:44 +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 msgid "Changeset status" msgstr "Statut du changeset" -#: rhodecode/templates/changeset/changeset.html:67 -#: rhodecode/templates/changeset/diff_block.html:22 +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 msgid "Raw diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:68 +#: kallithea/templates/changeset/changeset.html:58 msgid "Patch diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:69 -#: rhodecode/templates/changeset/diff_block.html:23 +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 msgid "Download diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "%d commentaire" msgstr[1] "%d commentaires" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "(%d inline)" msgid_plural "(%d inline)" msgstr[0] "(et %d en ligne)" msgstr[1] "(et %d en ligne)" -#: rhodecode/templates/changeset/changeset.html:103 -#: rhodecode/templates/changeset/changeset_range.html:82 +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 msgid "merge" msgstr "Fusion" -#: rhodecode/templates/changeset/changeset.html:126 -#: rhodecode/templates/compare/compare_diff.html:40 -#: rhodecode/templates/pullrequests/pullrequest_show.html:113 +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 #, python-format msgid "%s file changed" msgid_plural "%s files changed" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:128 -#: rhodecode/templates/compare/compare_diff.html:42 -#: rhodecode/templates/pullrequests/pullrequest_show.html:115 +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 #, python-format msgid "%s file changed with %s insertions and %s deletions" msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Showing a huge diff might take some time and resources" msgstr "" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Show full diff" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:30 -#, python-format -msgid "Status change on pull request #%s" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:32 +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 +#, python-format +msgid "Vote on pull request #%s" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 #, python-format msgid "Comment on pull request #%s" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:55 +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Status change on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Comment on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:63 msgid "Submitting..." msgstr "Envoi…" -#: rhodecode/templates/changeset/changeset_file_comment.html:58 +#: kallithea/templates/changeset/changeset_file_comment.html:66 msgid "Commenting on line {1}." msgstr "Commentaire sur la ligne {1}." -#: rhodecode/templates/changeset/changeset_file_comment.html:59 -#: rhodecode/templates/changeset/changeset_file_comment.html:145 +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 #, python-format msgid "Comments parsed using %s syntax with %s support." -msgstr "Les commentaires sont analysés avec la syntaxe %s, avec le support de la commande %s." - -#: rhodecode/templates/changeset/changeset_file_comment.html:61 -#: rhodecode/templates/changeset/changeset_file_comment.html:147 -msgid "" -"Use @username inside this text to send notification to this RhodeCode user" -msgstr "Utilisez @nomutilisateur dans ce texte pour envoyer une notification à l’utilisateur RhodeCode en question." - -#: rhodecode/templates/changeset/changeset_file_comment.html:65 -#: rhodecode/templates/changeset/changeset_file_comment.html:152 +msgstr "" +"Les commentaires sont analysés avec la syntaxe %s, avec le support de la " +"commande %s." + +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "" +"Utilisez @nomutilisateur dans ce texte pour envoyer une notification à " +"l’utilisateur Kallithea en question." + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 msgid "Preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:72 -#: rhodecode/templates/changeset/changeset_file_comment.html:170 +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 msgid "Comment preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:80 -#: rhodecode/templates/changeset/changeset_file_comment.html:177 -#: rhodecode/templates/email_templates/changeset_comment.html:16 -#: rhodecode/templates/email_templates/pull_request_comment.html:16 +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 msgid "Comment" msgstr "Commentaire" -#: rhodecode/templates/changeset/changeset_file_comment.html:81 -msgid "Cancel" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "You need to be logged in to comment." msgstr "Vous devez être connecté pour poster des commentaires." -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "Login now" msgstr "Se connecter maintenant" -#: rhodecode/templates/changeset/changeset_file_comment.html:92 +#: kallithea/templates/changeset/changeset_file_comment.html:100 msgid "Hide" msgstr "Masquer" -#: rhodecode/templates/changeset/changeset_file_comment.html:149 -msgid "Change status" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:179 -msgid "Comment and close" -msgstr "Commenter et fermer" - -#: rhodecode/templates/changeset/changeset_range.html:5 +#: kallithea/templates/changeset/changeset_file_comment.html:159 +msgid "Vote for pull request status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:161 +msgid "Change changeset status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:179 +msgid "Close (when approved or rejected)" +msgstr "" + +#: kallithea/templates/changeset/changeset_range.html:5 #, python-format msgid "%s Changesets" msgstr "Changesets de %s" -#: rhodecode/templates/changeset/changeset_range.html:52 +#: kallithea/templates/changeset/changeset_range.html:59 msgid "Files affected" msgstr "Fichiers affectés" -#: rhodecode/templates/changeset/diff_block.html:21 +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 msgid "Show full diff for this file" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:29 +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Show full side-by-side diff for this file" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:38 msgid "Show inline comments" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:53 +#: kallithea/templates/changeset/diff_block.html:62 msgid "Show file at latest version in this repo" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:54 +#: kallithea/templates/changeset/diff_block.html:64 msgid "Show file at initial version in this repo" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:4 +#: kallithea/templates/compare/compare_cs.html:4 msgid "No changesets" msgstr "Aucun changeset" -#: rhodecode/templates/compare/compare_cs.html:32 +#: kallithea/templates/compare/compare_cs.html:8 msgid "Ancestor" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:5 +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 #, python-format msgid "%s Compare" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:9 +#: kallithea/templates/compare/compare_diff.html:16 msgid "Compare revisions" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:33 -#: rhodecode/templates/pullrequests/pullrequest_show.html:106 +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 #, python-format msgid "Showing %s commit" msgid_plural "Showing %s commits" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/compare/compare_diff.html:48 -#: rhodecode/templates/pullrequests/pullrequest_show.html:121 +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 msgid "No files" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -msgid "confirm to show potentially huge diff" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:54 -#: rhodecode/templates/summary/summary.html:69 +#: kallithea/templates/data_table/_dt_elements.html:63 msgid "Mercurial repository" msgstr "Dépôt Mercurial" -#: rhodecode/templates/data_table/_dt_elements.html:56 -#: rhodecode/templates/summary/summary.html:72 +#: kallithea/templates/data_table/_dt_elements.html:65 msgid "Git repository" msgstr "Dépôt Git" -#: rhodecode/templates/data_table/_dt_elements.html:74 -#, python-format -msgid "Fork of %s" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:88 +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "Dépôt public" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:96 msgid "No changesets yet" msgstr "Dépôt vide" -#: rhodecode/templates/data_table/_dt_elements.html:95 -#: rhodecode/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 #, python-format msgid "Subscribe to %s rss feed" msgstr "S’abonner au flux RSS de %s" -#: rhodecode/templates/data_table/_dt_elements.html:103 -#: rhodecode/templates/data_table/_dt_elements.html:105 +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 #, python-format msgid "Subscribe to %s atom feed" msgstr "S’abonner au flux ATOM de %s" -#: rhodecode/templates/data_table/_dt_elements.html:122 -#, python-format -msgid "Confirm to delete this repository: %s" -msgstr "Voulez-vous vraiment supprimer le dépôt %s ?" - -#: rhodecode/templates/data_table/_dt_elements.html:137 -#, python-format -msgid "Confirm to delete this user: %s" -msgstr "Voulez-vous vraiment supprimer l’utilisateur « %s » ?" - -#: rhodecode/templates/email_templates/changeset_comment.html:4 -#: rhodecode/templates/email_templates/pull_request.html:4 -#: rhodecode/templates/email_templates/pull_request_comment.html:4 -msgid "URL" -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:6 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:6 #, python-format msgid "%s commented on a %s changeset." msgstr "" -#: rhodecode/templates/email_templates/changeset_comment.html:14 +#: kallithea/templates/email_templates/changeset_comment.html:9 msgid "The changeset status was changed to" msgstr "" -#: rhodecode/templates/email_templates/main.html:8 -msgid "This is a notification from RhodeCode." -msgstr "" - -#: rhodecode/templates/email_templates/password_reset.html:4 +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:4 #, python-format msgid "Hello %s" msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:5 +#: kallithea/templates/email_templates/password_reset.html:5 msgid "We received a request to create a new password for your account." msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:6 +#: kallithea/templates/email_templates/password_reset.html:6 msgid "You can generate it by clicking following URL" msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:10 +#: kallithea/templates/email_templates/password_reset.html:10 msgid "Please ignore this email if you did not request a new password ." msgstr "" -#: rhodecode/templates/email_templates/pull_request.html:6 +#: kallithea/templates/email_templates/pull_request.html:6 #, python-format msgid "" -"%s opened a pull request for repository %s and wants you to review changes." -msgstr "" - -#: rhodecode/templates/email_templates/pull_request.html:8 -#: rhodecode/templates/pullrequests/pullrequest.html:34 -#: rhodecode/templates/pullrequests/pullrequest_data.html:14 -#: rhodecode/templates/pullrequests/pullrequest_show.html:25 +"%s opened a pull request for repository %s and wants you to review " +"changes." +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 msgid "Title" msgstr "Titre" -#: rhodecode/templates/email_templates/pull_request_comment.html:6 +#: kallithea/templates/email_templates/pull_request_comment.html:6 #, python-format msgid "%s commented on pull request \"%s\"" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:10 +#: kallithea/templates/email_templates/pull_request_comment.html:10 msgid "Pull request was closed with status" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:12 +#: kallithea/templates/email_templates/pull_request_comment.html:12 msgid "Pull request changed status" msgstr "" -#: rhodecode/templates/email_templates/registration.html:6 +#: kallithea/templates/email_templates/registration.html:6 msgid "View this user here" msgstr "" -#: rhodecode/templates/errors/error_document.html:55 +#: kallithea/templates/errors/error_document.html:47 #, python-format msgid "You will be redirected to %s in %s seconds" msgstr "Vous serez redirigé vers %s dans %s secondes." -#: rhodecode/templates/files/file_diff.html:4 +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 +msgid "File diff" +msgstr "Diff de fichier" + +#: kallithea/templates/files/diff_2way.html:58 +msgid "ignore white space" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:59 +msgid "turn on edit mode" +msgstr "" + +#: kallithea/templates/files/file_diff.html:4 #, python-format msgid "%s File Diff" msgstr "" -#: rhodecode/templates/files/file_diff.html:8 -msgid "File diff" -msgstr "Diff de fichier" - -#: rhodecode/templates/files/files.html:4 -#: rhodecode/templates/files/files.html:76 +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 #, python-format msgid "%s Files" msgstr "Fichiers de %s" -#: rhodecode/templates/files/files.html:30 -#: rhodecode/templates/files/files_add.html:31 -#: rhodecode/templates/files/files_edit.html:31 -msgid "Branch" -msgstr "" - -#: rhodecode/templates/files/files_add.html:4 +#: kallithea/templates/files/files_add.html:4 #, python-format msgid "%s Files Add" msgstr "" -#: rhodecode/templates/files/files_add.html:19 -msgid "Add file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:43 -msgid "File Name" -msgstr "Nom de fichier" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:56 +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" +msgstr "Ajouter un nouveau fichier" + +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 +msgid "Location" +msgstr "Emplacement" + +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 msgid "or" msgstr "ou" -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:52 -msgid "Upload file" -msgstr "Téléverser un fichier" - -#: rhodecode/templates/files/files_add.html:56 -msgid "Create new file" -msgstr "Créer un nouveau fichier" - -#: rhodecode/templates/files/files_add.html:61 -#: rhodecode/templates/files/files_edit.html:37 -#: rhodecode/templates/files/files_ypjax.html:3 -msgid "Location" -msgstr "Emplacement" - -#: rhodecode/templates/files/files_add.html:65 -msgid "use / to separate directories" -msgstr "Utilisez / pour séparer les répertoires" - -#: rhodecode/templates/files/files_add.html:79 -#: rhodecode/templates/files/files_edit.html:65 +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:58 +msgid "New file mode" +msgstr "" + +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 msgid "Commit changes" msgstr "Commiter les changements" -#: rhodecode/templates/files/files_browser.html:13 -msgid "View" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:14 +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:14 msgid "Previous revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:16 +#: kallithea/templates/files/files_browser.html:16 msgid "Next revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:23 +#: kallithea/templates/files/files_browser.html:22 msgid "Follow current branch" msgstr "" -#: rhodecode/templates/files/files_browser.html:27 -msgid "Search file list" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:35 +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:29 msgid "Loading file list..." msgstr "Chargement de la liste des fichiers…" -#: rhodecode/templates/files/files_browser.html:48 +#: kallithea/templates/files/files_browser.html:42 msgid "Size" msgstr "Taille" -#: rhodecode/templates/files/files_browser.html:49 +#: kallithea/templates/files/files_browser.html:43 msgid "Mimetype" msgstr "Type MIME" -#: rhodecode/templates/files/files_browser.html:50 +#: kallithea/templates/files/files_browser.html:44 msgid "Last Revision" msgstr "Dernière révision" -#: rhodecode/templates/files/files_browser.html:51 +#: kallithea/templates/files/files_browser.html:45 msgid "Last modified" msgstr "Dernière modification" -#: rhodecode/templates/files/files_browser.html:52 +#: kallithea/templates/files/files_browser.html:46 msgid "Last committer" msgstr "Dernier commiteur" -#: rhodecode/templates/files/files_edit.html:4 -#, python-format -msgid "%s Files Edit" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:19 +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:25 msgid "Edit file" msgstr "" -#: rhodecode/templates/files/files_edit.html:47 -#: rhodecode/templates/files/files_source.html:23 -msgid "Show annotation" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:49 -#: rhodecode/templates/files/files_source.html:26 -msgid "Download as raw" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:52 +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:58 msgid "Source" msgstr "" -#: rhodecode/templates/files/files_edit.html:57 +#: kallithea/templates/files/files_edit.html:63 msgid "Editing file" msgstr "Édition du fichier" -#: rhodecode/templates/files/files_history_box.html:2 -msgid "History" -msgstr "Historique" - -#: rhodecode/templates/files/files_history_box.html:9 -msgid "Diff to revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:10 -msgid "Show at revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:11 -msgid "Show full history" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:16 +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 #, python-format msgid "%s author" msgid_plural "%s authors" msgstr[0] "%s auteur" msgstr[1] "%s auteurs" -#: rhodecode/templates/files/files_source.html:6 -msgid "Load file history" -msgstr "" - -#: rhodecode/templates/files/files_source.html:21 -msgid "Show source" -msgstr "" - -#: rhodecode/templates/files/files_source.html:29 -#, python-format -msgid "Edit on branch:%s" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 -msgid "Edit on branch:?" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:8 +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:11 +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" +msgstr "" + +#: kallithea/templates/files/files_source.html:38 +#, python-format +msgid "Edit on Branch:%s" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "" + +#: kallithea/templates/files/files_source.html:44 msgid "Editing files allowed only when on branch head revision" msgstr "" -#: rhodecode/templates/files/files_source.html:46 +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:61 #, python-format msgid "Binary file (%s)" msgstr "Fichier binaire (%s)" -#: rhodecode/templates/files/files_source.html:55 +#: kallithea/templates/files/files_source.html:71 msgid "File is too big to display" msgstr "Ce fichier est trop gros pour être affiché." -#: rhodecode/templates/files/files_ypjax.html:5 +#: kallithea/templates/files/files_ypjax.html:5 msgid "annotation" msgstr "annotation" -#: rhodecode/templates/files/files_ypjax.html:15 -msgid "Go back" -msgstr "Revenir en arrière" - -#: rhodecode/templates/files/files_ypjax.html:16 +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:24 msgid "No files at given path" msgstr "Aucun fichier à cet endroit" -#: rhodecode/templates/followers/followers.html:5 +#: kallithea/templates/followers/followers.html:5 #, python-format msgid "%s Followers" msgstr "Followers de %s" -#: rhodecode/templates/followers/followers.html:9 -#: rhodecode/templates/summary/summary.html:183 -#: rhodecode/templates/summary/summary.html:184 +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 msgid "Followers" msgstr "Followers" -#: rhodecode/templates/followers/followers_data.html:12 +#: kallithea/templates/followers/followers_data.html:12 msgid "Started following -" msgstr "A commencé à suivre le dépôt :" -#: rhodecode/templates/forks/fork.html:5 -#, python-format -msgid "%s Fork" -msgstr "Fork de %s" - -#: rhodecode/templates/forks/fork.html:28 +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:30 msgid "Fork name" msgstr "Nom du fork" -#: rhodecode/templates/forks/fork.html:65 +#: kallithea/templates/forks/fork.html:71 msgid "Private" msgstr "Privé" -#: rhodecode/templates/forks/fork.html:74 +#: kallithea/templates/forks/fork.html:80 msgid "Copy permissions" msgstr "Copier les permissions" -#: rhodecode/templates/forks/fork.html:78 +#: kallithea/templates/forks/fork.html:84 msgid "Copy permissions from forked repository" msgstr "Copier les permissions depuis le dépôt forké" -#: rhodecode/templates/forks/fork.html:84 +#: kallithea/templates/forks/fork.html:90 msgid "Update after clone" msgstr "MÀJ après le clonage" -#: rhodecode/templates/forks/fork.html:88 +#: kallithea/templates/forks/fork.html:94 msgid "Checkout source after making a clone" msgstr "Mettre à jour depuis la source après clonage" -#: rhodecode/templates/forks/fork.html:93 -msgid "Fork this repository" -msgstr "" - -#: rhodecode/templates/forks/forks.html:5 +#: kallithea/templates/forks/fork.html:99 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 #, python-format msgid "%s Forks" msgstr "Forks de %s" -#: rhodecode/templates/forks/forks.html:9 -#: rhodecode/templates/summary/summary.html:189 -#: rhodecode/templates/summary/summary.html:190 +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 msgid "Forks" msgstr "Forks" -#: rhodecode/templates/forks/forks_data.html:17 +#: kallithea/templates/forks/forks_data.html:17 msgid "Forked" msgstr "" -#: rhodecode/templates/forks/forks_data.html:42 +#: kallithea/templates/forks/forks_data.html:42 msgid "There are no forks yet" msgstr "Il n’y a pas encore de forks." -#: rhodecode/templates/journal/journal.html:21 +#: kallithea/templates/journal/journal.html:24 msgid "ATOM journal feed" msgstr "Flux ATOM du journal" -#: rhodecode/templates/journal/journal.html:22 +#: kallithea/templates/journal/journal.html:25 msgid "RSS journal feed" msgstr "Flux RSS du journal" -#: rhodecode/templates/journal/journal.html:32 -msgid "Refresh" -msgstr "Rafraîchir" - -#: rhodecode/templates/journal/journal.html:35 -#: rhodecode/templates/journal/public_journal.html:24 -msgid "ATOM feed" -msgstr "Flux ATOM" - -#: rhodecode/templates/journal/journal.html:51 -msgid "Watched" -msgstr "Surveillé" - -#: rhodecode/templates/journal/journal_data.html:55 +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "Mes dépôts" + +#: kallithea/templates/journal/journal_data.html:55 msgid "No entries yet" msgstr "Aucune entrée pour le moment" -#: rhodecode/templates/journal/public_journal.html:4 -#: rhodecode/templates/journal/public_journal.html:21 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 msgid "Public Journal" msgstr "Journal public" -#: rhodecode/templates/journal/public_journal.html:13 +#: kallithea/templates/journal/public_journal.html:16 msgid "ATOM public journal feed" msgstr "Flux ATOM du journal public" -#: rhodecode/templates/journal/public_journal.html:14 +#: kallithea/templates/journal/public_journal.html:17 msgid "RSS public journal feed" msgstr "Flux RSS du journal public" -#: rhodecode/templates/pullrequests/pullrequest.html:4 -#: rhodecode/templates/pullrequests/pullrequest.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 msgid "New pull request" msgstr "Nouvelle requête de pull" -#: rhodecode/templates/pullrequests/pullrequest.html:25 -msgid "Create new pull request" -msgstr "Nouvelle requête de pull" - -#: rhodecode/templates/pullrequests/pullrequest.html:47 +#: kallithea/templates/pullrequests/pullrequest.html:44 msgid "Write a short description on this pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:53 +#: kallithea/templates/pullrequests/pullrequest.html:50 msgid "Changeset flow" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:60 -#: rhodecode/templates/pullrequests/pullrequest_show.html:65 +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 msgid "Origin repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:85 -msgid "Send pull request" -msgstr "Envoyer la requête de pull" - -#: rhodecode/templates/pullrequests/pullrequest.html:94 -#: rhodecode/templates/pullrequests/pullrequest_show.html:137 +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 msgid "Pull request reviewers" msgstr "Relecteurs de la requête de pull" -#: rhodecode/templates/pullrequests/pullrequest.html:103 -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 msgid "owner" msgstr "Propriétaire" -#: rhodecode/templates/pullrequests/pullrequest.html:115 +#: kallithea/templates/pullrequests/pullrequest.html:114 msgid "Add reviewer to this pull request." msgstr "Ajouter un relecteur à cette requête de pull." -#: rhodecode/templates/pullrequests/pullrequest.html:129 +#: kallithea/templates/pullrequests/pullrequest.html:128 msgid "Detailed compare view" msgstr "Comparaison détaillée" -#: rhodecode/templates/pullrequests/pullrequest.html:150 +#: kallithea/templates/pullrequests/pullrequest.html:149 msgid "Destination repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:4 +#: kallithea/templates/pullrequests/pullrequest_show.html:4 #, python-format msgid "%s Pull Request #%s" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:35 +#: kallithea/templates/pullrequests/pullrequest_show.html:36 msgid "Review status" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:40 -msgid "Pull request status" -msgstr "Statut de la requête de pull" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 +msgid "Pull request status calculated from votes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:56 msgid "Still not reviewed by" msgstr "Pas encore relue par" -#: rhodecode/templates/pullrequests/pullrequest_show.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:60 #, python-format msgid "%d reviewer" msgid_plural "%d reviewers" msgstr[0] "%d relecteur" msgstr[1] "%d relecteurs" -#: rhodecode/templates/pullrequests/pullrequest_show.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:62 msgid "Pull request was reviewed by all reviewers" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:89 -msgid "Created on" -msgstr "Créé le" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:102 +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 +msgid "Pull changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "reviewer" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:133 +msgid "Add or remove reviewer to this pull request." +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:137 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 msgid "Compare view" msgstr "Vue de comparaison" -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 -msgid "reviewer" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:164 -msgid "Add or remove reviewer to this pull request." -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:168 -msgid "Save changes" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:4 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 #, python-format msgid "%s Pull Requests" msgstr "" -#: rhodecode/templates/search/search.html:6 -msgid "Search repository" -msgstr "" - -#: rhodecode/templates/search/search.html:8 -#: rhodecode/templates/search/search.html:16 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 +#, python-format +msgid "Pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 +#, python-format +msgid "Pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 +msgid "Hide closed pull requests" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 +msgid "Show closed pull requests too" +msgstr "" + +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 msgid "Search in all repositories" msgstr "Rechercher dans tous les dépôts" -#: rhodecode/templates/search/search.html:50 +#: kallithea/templates/search/search.html:53 msgid "Search term" msgstr "Termes de la recherches" -#: rhodecode/templates/search/search.html:62 +#: kallithea/templates/search/search.html:65 msgid "Search in" msgstr "Rechercher dans" -#: rhodecode/templates/search/search.html:65 +#: kallithea/templates/search/search.html:68 msgid "File contents" msgstr "Le contenu des fichiers" -#: rhodecode/templates/search/search.html:66 +#: kallithea/templates/search/search.html:69 msgid "Commit messages" msgstr "Les messages de commit" -#: rhodecode/templates/search/search.html:67 +#: kallithea/templates/search/search.html:70 msgid "File names" msgstr "Les noms de fichiers" -#: rhodecode/templates/search/search_commit.html:35 -#: rhodecode/templates/search/search_content.html:21 -#: rhodecode/templates/search/search_path.html:15 +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 msgid "Permission denied" msgstr "Permission refusée" -#: rhodecode/templates/summary/summary.html:4 +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 +#, python-format +msgid "%s ATOM feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 +#, python-format +msgid "%s RSS feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "Statistiques obtenues :" + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "Fichiers" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "commits" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "fichiers ajoutés" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "fichiers modifiés" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "fichiers supprimés" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "commit" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "fichier ajouté" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "fichié modifié" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "fichier supprimé" + +#: kallithea/templates/summary/summary.html:4 #, python-format msgid "%s Summary" msgstr "Résumé de %s" -#: rhodecode/templates/summary/summary.html:16 -#, python-format -msgid "%s ATOM feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:17 -#, python-format -msgid "%s RSS feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:62 +#: kallithea/templates/summary/summary.html:16 #, python-format msgid "Repository locked by %s" msgstr "" -#: rhodecode/templates/summary/summary.html:64 +#: kallithea/templates/summary/summary.html:18 msgid "Repository unlocked" msgstr "" -#: rhodecode/templates/summary/summary.html:83 -#, python-format -msgid "Non changable ID %s" -msgstr "Identifiant permanent : %s" - -#: rhodecode/templates/summary/summary.html:88 -msgid "Public" -msgstr "" - -#: rhodecode/templates/summary/summary.html:88 -#: rhodecode/templates/summary/summary.html:89 -msgid "Fork of" -msgstr "Fork de" - -#: rhodecode/templates/summary/summary.html:97 -msgid "Remote clone" -msgstr "" - -#: rhodecode/templates/summary/summary.html:117 -msgid "Contact" -msgstr "Contact" - -#: rhodecode/templates/summary/summary.html:131 +#: kallithea/templates/summary/summary.html:76 msgid "Clone url" msgstr "URL de clone" -#: rhodecode/templates/summary/summary.html:136 +#: kallithea/templates/summary/summary.html:81 msgid "Show by Name" msgstr "Afficher par nom" -#: rhodecode/templates/summary/summary.html:137 +#: kallithea/templates/summary/summary.html:82 msgid "Show by ID" msgstr "Afficher par ID" -#: rhodecode/templates/summary/summary.html:143 +#: kallithea/templates/summary/summary.html:99 msgid "Trending files" msgstr "Populaires" -#: rhodecode/templates/summary/summary.html:151 -#: rhodecode/templates/summary/summary.html:167 -msgid "Enable" -msgstr "" - -#: rhodecode/templates/summary/summary.html:159 +#: kallithea/templates/summary/summary.html:115 msgid "Download" msgstr "Téléchargements" -#: rhodecode/templates/summary/summary.html:163 +#: kallithea/templates/summary/summary.html:119 msgid "There are no downloads yet" msgstr "Il n’y a pas encore de téléchargements proposés." -#: rhodecode/templates/summary/summary.html:165 +#: kallithea/templates/summary/summary.html:121 msgid "Downloads are disabled for this repository" msgstr "Les téléchargements sont désactivés pour ce dépôt." -#: rhodecode/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:127 msgid "Download as zip" msgstr "Télécharger en ZIP" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "Check this to download archive with subrepos" msgstr "Télécharger une archive contenant également les sous-dépôts éventuels" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "with subrepos" msgstr "avec les sous-dépôts" -#: rhodecode/templates/summary/summary.html:197 +#: kallithea/templates/summary/summary.html:163 msgid "Repository Size" msgstr "" -#: rhodecode/templates/summary/summary.html:204 -#: rhodecode/templates/summary/summary.html:206 +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 msgid "Feed" msgstr "" -#: rhodecode/templates/summary/summary.html:224 -msgid "Commit activity by day / author" -msgstr "Activité de commit par jour et par auteur" - -#: rhodecode/templates/summary/summary.html:232 -msgid "enable" -msgstr "Activer" - -#: rhodecode/templates/summary/summary.html:235 -msgid "Stats gathered: " -msgstr "Statistiques obtenues :" - -#: rhodecode/templates/summary/summary.html:256 +#: kallithea/templates/summary/summary.html:193 msgid "Latest changes" msgstr "" -#: rhodecode/templates/summary/summary.html:258 +#: kallithea/templates/summary/summary.html:195 msgid "Quick start" msgstr "Démarrage rapide" -#: rhodecode/templates/summary/summary.html:272 -#, python-format -msgid "Readme file from revision %s" -msgstr "" - -#: rhodecode/templates/summary/summary.html:332 +#: kallithea/templates/summary/summary.html:209 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:299 #, python-format msgid "Download %s as %s" msgstr "Télécharger %s comme archive %s" -#: rhodecode/templates/summary/summary.html:379 -msgid "files" -msgstr "Fichiers" - -#: rhodecode/templates/summary/summary.html:689 -msgid "commits" -msgstr "commits" - -#: rhodecode/templates/summary/summary.html:690 -msgid "files added" -msgstr "fichiers ajoutés" - -#: rhodecode/templates/summary/summary.html:691 -msgid "files changed" -msgstr "fichiers modifiés" - -#: rhodecode/templates/summary/summary.html:692 -msgid "files removed" -msgstr "fichiers supprimés" - -#: rhodecode/templates/summary/summary.html:694 -msgid "commit" -msgstr "commit" - -#: rhodecode/templates/summary/summary.html:695 -msgid "file added" -msgstr "fichier ajouté" - -#: rhodecode/templates/summary/summary.html:696 -msgid "file changed" -msgstr "fichié modifié" - -#: rhodecode/templates/summary/summary.html:697 -msgid "file removed" -msgstr "fichier supprimé" - -#: rhodecode/templates/tags/tags.html:5 +#: kallithea/templates/tags/tags.html:5 #, python-format msgid "%s Tags" msgstr "Tags de %s" -#: rhodecode/templates/tags/tags.html:26 +#: kallithea/templates/tags/tags.html:29 msgid "Compare tags" msgstr "" + diff --git a/rhodecode/i18n/how_to b/kallithea/i18n/how_to rename from rhodecode/i18n/how_to rename to kallithea/i18n/how_to --- a/rhodecode/i18n/how_to +++ b/kallithea/i18n/how_to @@ -4,14 +4,14 @@ Translations are available on transifex under:: - https://www.transifex.com/projects/p/RhodeCode/ + https://www.transifex.com/projects/p/Kallithea/ Preferred method is to register on transifex and request new language translation. manual creation of new language +++++++++++++++++++++++++++++++ -Dowload sources of RhodeCode. Run:: +Dowload sources of Kallithea. Run:: python setup.py develop @@ -25,14 +25,14 @@ Make sure all translation strings are ex Create new language by executing following command:: python setup.py init_catalog -l -This creates a new language under directory rhodecode/i18n/ +This creates a new language under directory kallithea/i18n/ Be sure to update transifex mapping under .tx/config for new language Edit the new PO file located in LC_MESSAGES directory with poedit or your favorite PO files editor. Do translations and at the end verify the translation file for any errors. This can be done by executing:: - msgfmt -f -c rhodecode/i18n//LC_MESSAGES/ + msgfmt -f -c kallithea/i18n//LC_MESSAGES/ finally compile the translations:: @@ -62,6 +62,6 @@ Edit test.ini file and set lang attribut lang= -Run RhodeCode tests by executing:: +Run Kallithea tests by executing:: nosetests diff --git a/rhodecode/i18n/ja/LC_MESSAGES/rhodecode.mo b/kallithea/i18n/ja/LC_MESSAGES/kallithea.mo rename from rhodecode/i18n/ja/LC_MESSAGES/rhodecode.mo rename to kallithea/i18n/ja/LC_MESSAGES/kallithea.mo index 0891b2f31d7a22dffaf5923932ef7612b61ce47a..fa52bcd49d92c9a5e15716d60195b5c9a51bc53a GIT binary patch literal 93328 zc%0n534D~*^*27WwpMDZb=O)Qu_#m$pl%fxMAj%sB!CN5m}Dl&Kr$0&CO}jyNm#;; z8@nvZ9tkR|vb9!i`?mh7wzk?lL@{{@HB$|A$SVGQwN4ZXA!(;AmaND zM81&(I}?lzL_ew&P9gYZ?vI8SDSVvZR|r0-<@OIm`#;h2w-vri@N9zrB={wQrwu~< zHwd0Y@LL-0GYIK}37$%@a1i7}uq5gH6ujwZAd*4mK&kt|Hcz$ye=J6xV z_qCzO7aodvx@aiIf7wvfH%P<7hhm%&g|VUNXM8B=VIski1Ro-}lHehN4-uR>4DSP)U&EyZ;oS{mvuN&eumG{+lDwPA`JT@%kN!di!epAkAMm66@=Bg5P9%(f9{Of)18x zx!np6jKnxzB-oq#F%o$B`Y6!njibV?A6o8tn`l4Sd{1@H&ENf(1Muqk+FqM}zNly_I+fa^4kd3x{V(2z{=TB{x3__R zwcG~09e+FO`zk?NvZ3>C*Y$Bb*40FURot)Jfseo4j(+@`;MWPBatF%i-=Y1u1M@VR zU@wAW?*N__DqN+oNz3iK1NFXi2k7XvJAl774S#Y6`qOy~+C6g&=BdXRq!*0Ax)?JC z`Q|8GqWRa2K|h}zgL(dy!jB2Ynf|{Eda5IMA;Hz(#kzc6;h(+>zJKzaSns{=1m17G z6Z4q56Z5qEPSD@??*x9E??gYpa2M+Dau?|G`nxc`)LmG=^>+aejSBbN1v>iaU7-Kp zYxu*vuztQc7WqyYi})^Mk?)GJz+=H!%=;~4LC4=6i}q7vfro`!{t1P9HQ&$1V&49! z^}aI}{rvB-z~{;1KtJCYhjJH>Lw~LuhjrY49L7In9Li51NF)~e9>Hq~zCI54JR<`9 zToXZicSS&lWf9buh@icDB3M^5Bf#Uz2>P=}l9=7lWQ&&~m@l^mmKV&;JyIzK<_K`1}&&?^c5L`Y61y1ncIG z66^!zCFtKn1ZxPcF9E*7QQ)&{6yx+}nk1msdr=F9L@5)IiKYSAEk50lqKXDS|;U5s}NAQJ7 z=-2U+F^+R4W1Qj1n8)6efzN9v1201+WBx`=#(a&_^rXh$Ga2}8(DVm1ym~Umy-Djm zFd6;(sg{3R^Sv_}a?@WYV?Hje0iXF!4d!u3jmq~Lj?`fMhA+FC;&5bR5^@E-Jk;XS(V+=Kjk?m@k;+=KqUq42$X(C+8&MZZtJ7kuMv zg~RW~xTfEW_7~m@ye_*}_kB&@b1(4pqNcy5>8)Dt-|qz;{`+3YdB@#{ee@gmA-(T? zz~_+rfR~Z?q2HzVVLbQUhx%q~c-ehuZ{vOF|E~K$|Igot_TSR-?`!@qOhG%RPC>bI zr-1KWLhwAM(F{{86JO9ZbV_}lw2ucv$u z?Va;Iq+ddiRK3tu1PhstzlVM6jqjn|e|!)7#Yt09@3jQ4A$TLf%LvY#iuvC=74?5O z75(|=RE+b)TCCgCYq8#X*Fq1yvKHxcYcbwOYSG@>THy6rf_(`7S1rbQLLKlLuG4;N z_^LXzH=qvq9bE@J71yEuDRrRV8FkYuZqs~k)`9e0>v8h%`1V?FS)tse9B{d&lQzadDfXXw&tpo1CHP=2X~8>gZC{%Pp8SsV>7d76(^20o(}9nY=_r5qbgY;Ar(>R1Plw#_)O5%{uT95%d^8<$ z#z`}P-@Y?|m(eqjf9eeI=e09X|IcS&e%_pc`T1xD>N$QU(l4Beb=P|)`rB_N##J~I z{rK)o;JIT$P z*8sdOX;41gfc7^vpg+$xU|wHr0R6nwfbqQE0DAbdmOp+L`g_tW=tCFJ!gz0h*3;bcb#{WX|e>4mII%zgw*V(Y6Ts<4}F-hSgv(cYz1g~PcAXvfkKO6c+ zYz|<<9L#Uy9Oz>&%>mv%oCEwEKNs_G_FVM8`&^XkHy7iK&P9JG6CA?r&P6}pA~=}W z?Oe!_H_QW_Cgvf%b{_Ea=se(a_dN9bCmP>25A}X-KKR1<^N~JsKKhlK54xQ;AN00v zKInY!eDw3R`M~qL^C8!swgBV0b^-7@VgbtCy#V8ASb%m`EI|2JG~Z!@v{i+^v=I5~ z7lJ+)F9iQtw-Ehr)bzazv94a$e1BR9y7`3QAcCD9P&wcMl>;<9?g7x#_y<4_6BX8L zzJ(8fZdYpj;~M`Y!MjPG+y4OQu-C)r&y^2rI}Zb&BObLs ze*6~==RFb%kxCw#@Cer7PaZ)(UVjAh@a7}H*ZYrP+{Z7%JYTQ~__%BlCl=;i(;YPVeiI^3!0zgVJnoF%~TDNE6> zbC-hN@-;kaDdeQGrQk2~mSP@$xD<5y)>72-@lves6PICK^jL;*3|WSLS1iN2oU#o2 z?qdW85`1GB_{#aq0WV$-dg!U}+U3CiP0NALvCBap(dDRjf|k2)IohA5`PVK7UGHA5 z=M2lSet)9n{-*i9xB}xjXNB4eR$#r{v;z1XzXJVeSOGjQT7hvtxdQn7iNe+u;6I;# z6#2S7ivIL{6yqNIDAK1riu%_-iuzx86!g;kD8_NxO2BhhV!Yp6iTUZi5_E9sO3-27 zmB2%P&3EHUv^RVu>iw0%cUJ>{$E^XMK4%TaJ#r1~FEwj0?@zA*eH~td`cHlg`d|0Q zfQN;TVSW98;FG+53EoO@&Et@_{_!}*fALz(?EXl)oUT=ZC(p}{9`TF)!FN?t}j{#`tG?7^fF)_@P6Amwa;k2yEXlub(p95 z>(Gy7>#z>DXg$AL2YPvD9q8&y>rw8E^}zGD)y1JxE}N}SHq3#QU4FtV;)~x zkNG%j1Ik~z0rd~paK#3cZ`h!GU<1nU+yFbra~pv7zi+@gxp*V^!?!nrpM7^D`j^>= z{x@s{o*&ip?Hf_w&o-hTuWtnXe6$gG`N}51Gd5w~&))>P7_H^DKR(XW>_V?O?{8RI^*8Fcl9My#Xr8X?DCM37Y6P+24D z`+XzoYi>k4ot^;Q9sdO6@GG7Gz0G+7`^Pg+KtB2S37o%Nx&`e_+=B1|f&&P?x&?gZ z%qEoUuducW_&(5t`TeK~a@vJkVfP=i6?kdb3i)!&R@DFcR;-&3wt^3LdlKbteiHLK z<4Mrrx+lS3b`cy(@C|~u@VK7>olkxW^HTQ|=zPUfsBiC6nD0M61-zg5H1K%A)1a5@ zo<{tzr-AQc4NrU;{hg!nPipx2r$N_;6@L6Q`uT-zfZyDP^8L4={@XNMwhi-e-!{xo z-8RtUjBTo4Yy+J=uHmhk{sS%dvu&V*SGQr_-`IwA{D*CrkM}hGob4#rWjn%o+tJ?T z+p$kywH@^oY}a$B?V!`!w}X$|r{!w5gFa?yc$dNhTK|u>tKOpU_uJ9WKX1o4KHLuc z{72!5JJ9YqJ5bLBJ5a9s4)BjFc7UIZ-GO>inm&04*46YKz{?Xmu)pos@XxirKWO;y z4vgzxJ5-L?iT<3l6ZyWr6ZK!X6L{&q6Xo(WzVA+yAGi~Ab@NWp^=&)RpSe4Mr=>el z|4M=+)`d1{`6sl!r!~BPC&u;sPPKFHRJ(`P^Y@*=%fA$UZWr1)VHf&!#xB&;Z5R5L zukgxU=->6bQ0~TEsPC3tkPAm^`G1ElzmutUH75BKKn49 zLJg1Gr~FOff_T3SZUu-#(}F^BnZPcb>!gJ@JRS-~CYe&<~+s6lnOlA1Z(QA^P*i55Z4A z)bQ7y2mk%n^J*7+9{r6ykMx<(V;)vNkM*P8J8(tIcX2=$+-u-A_;z5)&3{v-4+ z^&{Zvdm2CMN6*q*+ncy9~{$9rV82d8no&7S>pMM#6`Q&BL?SH=ve4X+NV4qj8{)=BhzJ;%# zp2e>yU1w7r^6WP2Z&9XEgjLh5!5o#?kqgq+=4i{Fjhd z=KK=rZ~jvCieCZ`$GwK}^mq;9xZ*YNk1-ma{2KcAsKT|cfnFP5!#MueYpD0_*MRrG zyoP$e`74wk`YY_ScmE1@%4G!S5&Y;^knd`Lt>=FP7ZUsp!Epp9ysqcxuOr_dUkARr zzJc}eoj1_#9dDpN%sfHiZ^xbbl{`#e+hu#9-&VCEyyGP;dx4=)Ay#@Q#*0-SF z9DECMb8A`~HCZTNHlu2k@(_ z{)qY}{SoxL=Z~O|zx@&O(!E*F@0-Cd);9xxt<9=u90WY?AjW;=L8K4UaD}GVY5eko zpo?b@f}Ve;u=OD5?=J^2-)FY~4?|n94r*JlA1-OZzP7&w<^IwFJpZ!=a^D%PX!l}; z*S6|>w_+TrR?Oe@R>%``ThYHiw}Rfk&_;Q9ylue47Y~8|^f{z_;}FWKtl%A9~?!e^Ec5zhHb%{002~ zg}>-HK0y2lA3*--qOku5=x_7`;A_bTXs_`DtdEyJfF6C?hZyIm57AEYL*Q%9hgg4m zKg7B^;UoCF4gLu64}1i=e(NLj|7(8*zZ{})&R?;=|JPs9kK_J^_P+Bsl&|?4>V5HV zsQ0+PWBzacJN#?!`#aX}kN*yQe(q!RKksAUam2?MfAPntKmIZB{HTVveGEEn({d+$ z0={_JC&<_D6SXUSg8bt@LA@(K0o^od{*ONaUXJ?*$yNlz|3JHcQux6?knfX!Am11M zsrx9wFv%~y|A~EV#J>QO|5E<^FN|;LzmWeI3Y-6h{(kf?=&5IYityE+VxGr+3VEgG zQ`EELQ>?e=H2n6b&~x7X6!P~cpQ4{9{u_GCssDyPbe6(z5hRf-bj`mZuYTb_z{{8a zgL3EnNA(pA7ySqHatFaXND<8Z2krhm)JewkJAyopGdclYr0@!YoNo|8?pF~(Zl{bO z*Lx2^rn_2#%m<&=^t~GXIl+qvpKlOk`Uri#lhDObf-G-O`aJ4i`FXV0NRa7s4?&hE z-y=AV%D;15C&&k1>?C~S?k^($LW0b1Rug3X;W>ii2zENYlk8)~1R3v>jz_!O2=e~% z7D2|(d0#?5hJFe4rN4x6))Qnq+G2u?x2Fm6KJ>FMVcb`o&?!_)@Y)m5uLCDwya!J} zf8IL*csRLpCz<~XJEPn+8t&g2>EG3GvNPIm(0ofYeN|`R=V^kxE)HmXn}+|X;VxfB zxyuRix$ZSzMt>F%WcpsJ;T>PrdcKT$+rEtQfBiDrKmJ6_=a~eVKMXk$<-d0#@-HXI zd~74Zr370DvL5iguV5VS6XbpIOJBu2_4z8w-TqbJrSz-F*P!uh2(n(*M3DEpT?CoW ze(NOkr-~r2`>7{ke2X;xQH5JHexHV)KMD2zQp11H^bbzLxIa-CJ{j{o`^Ng-@Q0`F-_d^y6cKY;XO_*D#K*1bMw*_cfG{X#CW#A^*~^q5iF3L%Yur`Jq7(7a0=2#D!lI$(C6AyP~WSkApbk3pg-rHivIOG744RsiuAfumCjE^`L{IR ziKii7{%Ppfu+vaaiNc1{(C!w3tVh3g8t``TH1zKsE&nfq?04?vqj{2sZj{M6A z$~ghS;ROG2I_fVt1NA2evOKux4D_#sAnP5cp4mzCj<~`-XQKYEoQ3+oaTe;o^el|0 z&sm`7?-Jzwy!0%c|Fb}^zdQ?g`^#Bq_k^>NulL#L&w{g2&-SxX|F6zQ{eM0i0Z~e)}pMe-8N0Bj*7BzdQ&0=L=s)e@Y3)2u}Pu+WDQvf2iTlor~~U z=VCnF&ISIzeJ<##A3;86j}p9>;49~%AH%+Zah84q{j2*1=xhN&wu?Qc@l6C-4%+h# zwD((uAAAFNIQ~4;*W*0I4^%jYAj`3Lp9lQaod-U+`8@E2=g$M*{1-vqce|Y5N%ZXr z=cC@I&j+9Q_4!!Or-d=EcZ5;@6Jg;0xiIMJU>N=Q`~_(5T!Jib4^TMf0;H!dzF-^Db$xsnz^`|~y!Pw@db@%k@2Al&Xg5xf<=h5^Z*~FRzI`Fm`(B9t z-gP1B$!Pq&7owlbE=2z4E(E@Qej)ntwx<6>%U$qI;G-Ks)~8|wS#Esto0$KWZ(<+* zo5G%50pkiE?}~oB*%kGE)D`&q`bAi0*ItD9c?4N5+Hn!;Jxq}AHT;9%1g4vd!JnVG z81wj!!Y!exXX_ug#ftMg(MB#FUuU!KAIjIN2qk16!f*u%uV-N7tmwKSSzY}D?tc&vi zi}QfzNAuACSM$)nP(H$!n18}P`FI20 z@5c&XC-^DJbB8p&EWQTqF1!Zy>`?f^HCR8dT?2k~ z;>DFt}@3q$g??1m5m>T$u$eX<_RA#o!0Xou^7;Rj!%+XGVW5NNVZirC!%*)RZw9>NW~3Ktc$|i(-we8WgrM95z8T~E z<;|G?k2KtCIOb{iaD?lJqaTkA2Y=r`9Q@^@;n?5$7GivN7oxp~3Q=x1!7_rsF2wly z-h%Pnb_?oXpzwzZKfVR?bjb+hA2I^+ZA9TS8vnJTPGbN3RuSq;7NNcM8h%0HrwT6} ziE`sd>Uc(iJ{}thIpU>}z|UJF!Pnj+$aa^WqdJM7LM6dJ5L`A2^LgKB;CoWy%l`_#M@AA{B5Z3l-oOro#>3) zQU3PZ!7s-VqMy4r3O_W$W#270+&;beu2%TR8ohF{chOBvexTN&E?y=-_!W#G~er*{(FUo6@FBX_WoUtc{@1{`aL6#@;&1!N5@f5 zL}7Ux{Y%Et|NAuGT#etT@jDd0pzt*<-x7zu^yfI}^@BL@amsj%ulIQLZ}fPS8#f;H zRuSAoa0ccAHclOLR}?$XiuiQ4vnX?yiod zb7bed@nnLs*CeZhvm~oxoSukH>Og&|SXn%siKVDOJQ2PrQc)4ll*b~$nbXub^&p*& zl*NK`Oo}8jY3W)fNp(+*`#W)A*KSp*vGHj4bf2(%X5yKO7*`QBsIWdIIvS}_Ai?rv zb;>}AsEjA7GcorIk;z1+-1(3wbSIXwza=3ZD@i7z?w3T?#3CsJDI(3YTpEi-`Lo~1 z;lrH34aww$%1CO0WV#_0NtBew+1Z(%{b z!FhTsYq{LvHvI|KE?VfrX#WX5>DD&y%i=j7>$3oT@* z2Q;oBBS#j72c}X~#bv#&=p&=;S5gwI%0!AQV)^J#EW|8>{t>r|S46{u8Lbk&nW%*M zhy>iV?F(83MiKs<4=bLA872}2qn8LGv2w~{HUf^LZOlNSA_)kIRVF9K97fKl%9PWn zZL-fdnX9WRl98w`tSF(gBvVlno*0j~xR$Ib?`Tp!#-))*Y>`sDlP~KD>BS^gu1x_syh}b zDbJcLr-hUVUsQQXIW6#nRk#Q9G-|h;WEm#LlInDZ7*=*G+=##aw9^3bjm*(>@BdcE zh&dizpDcd)KaVV(UKT%voRX827Pxhn1@iVsypre{`wq!dL>&3yeu-qFrZQO#_AYWlWNHk zrb0F$n)xHogoRZWD>$mX3876UDVeBdcMQ4nt8|maWdqn~t}3J`Nsp-`j9K!fMQZOz z_UZ(oaRLxetDAZia+fX^e5hYloF%Amx>~}eG!ZpMoD5DBg36UBJdBd6QY0Zz9?}aO z@sC7-s7R@H31rFCRK?_rRctf!o?y7JqPi^3OvM{rWMs>JP)7P$Y{u{np2^r`(zFvU zTM6}>NOaCZSGc%3UXjV;=`u|?NtLn6V%E?oCPTWY?6lE%n$x188{&xw(-cca)_1sD z*L3%gQB9o>ra4z%y@8~y5O#D0l5V#68>(6ElLe73p=st^+)E~^VX+iVbDW04GDbR_ zM@Wybu0+VZL5C9RpT*QHtRpo|fXISF3Dz$nMCWBHEMQ|I#e%hCLY8L1)Qd)xAr8gc z3MuUw(i{jinGDw&l{J<&C1f$h>>Y{)=^C~l#41X;g^0*V{UcR0$Vdq4c{n2YraDc8 zYsq28Se-WUhQKwLoRlCAN7Lg4_Ou$`4pZh zeTRj>GSaynhsY3yUg#Z$s>4R$?Oz__v2(w;pF{zoZ!nJ}O$rsItBYl_keNGBDw+wi zqcr+R@hs}3i3CcB{z{2kkRT#?r5lM@NR%;J4k}hrSj04}6~ig|lZwq6Z$%6WCZ>io zE0M7ywl?L=S~{8H!I#7mQK4l|d^DDw0LGplzCBqTt|ZBa*)9>St-jitJdGn}_72^v zI3_0Q1`VD^C(K4aiMu#o75qiiAm&E47zksB7C2tCmF~z9Rp9C=9CkK$GkeU9MbQKa z&|)H~HsMsp6+4a4Bo)U=qe?hc@oa|rCo3u2Jh;ZMl~^oFR73Gv;nLF-ThdRYO+ju`}C|*=tYJs-VW2u!tIo zFk3>x_x7HWZ{nQ-!i5>L)oI8s;dBi#-N}x5DqUSwMWlj~#F>Y|Ol*SMI}@z*rfN`< z#TKg2GOju?&dh4W2pR}PeG|jX-xDyM42Ue0y+w9QlbFh?(2400F4pGh%XE#&B@-!2 z=R5g1VaG76<_kM6*>csrw- zt3)L9zssthx03^W+1uZ$8Wo~+qp%fZq`I<^hz&dvE#X(?^Zg~V zs!&YuB8z!!YI3|0a}9`A7(|b7VG8C@PaL!uZ2j+gr*!*zpULI78ii>Yri5{84j!kRnE^m{ zGT)+W3<%^~Iil76F~G;4vLZbBV3M^Oi|TG9q-3H*`=g9ri?K=N^YfJ?=}anF6HZp}QErC2#JZX@AXVI~ zA(Bc*8ZPTA?mo(gpv>e(I4v7RctA37F)KL4KS`7`+ErhQ2bDMzZ6J$5_{%5Td<3B(l50!jlM&#!s!WYNGXoPm9SU4UO*Bj~ zPspLOFqnLQuC$3LFC$%!7=&;ow&^6$DWq0JQe`m=C_9aIWdibDDvO%a!RjpfA*F&vj@%8|h6pPc?<*R#gp#Zn>QsUdkqb#t1056Dzyxcr zUAtAr6W!x1BBdfky(y8F<*XVRB4HB2s$)SJN%<@D<&L_1hLx#^T3wOIIOk($)};}X zE@$PnB2pY9ViD_PiP=GI@l*JxFWt)+kqE1_=%{u?DpnG&ii@%|FxX%(N=~js%bFh~ zG90;-5gt02^9VKPI0`sIDcM&{Q#tamL~^7&X;>M&+CgwuZ0Ow0sM({Bl+o;dN6Kf* zH%H1FL?|7~eFTiUW!j%#U%sQO)e#!o$t~6=%Spp=q&PwuV%628U8Vh{CNo3vtgyZm zStXm7*EpcDvis6^oY*`;V?t+>eZcV?Wk@MsNP7ZayZImp7p~GJXXSRR&t@DN#C{v% zZ^hdDR-`c-16e702X!l7)qSVnr-5Mo*C&z;Yvw#SWW^c-n~B+M^DalElW0TAC7H zlxRM6Cq+x?W*Q4V6Y?d_WC|Qr7aMrU^)wrlWb3BxJ-(eOd}~rHDvksY@tqZg^;onAYUfd=c`hWGhpvhDLQ8I^?ywau^ z{bdccpfEJZr-p?F7mTESW$>YbO=z&FVih5g8u^cB_vKAiA}ivhv|rFTB*bQShFL7y?5Ky+oxa@TH5)!l93mKAyJ6&g*`U)wMd8eEYq=B^6x zC~|>n-{55UhDgZ-g2^&koc)NO)QFH%k|Ysoa7vF~s#6t^NgW?KK9YbKrdfz~CdN`W zf6VV3KF0sBLWFfjQgNp6v{{a$Mhvw)G>EN~u!|otzZCD56*b4+=)Gyu6e?p=`1|7W zOs48$7P;greK8zq4NCYk)K?k3+*C=QeAZQN@aNVa z?p6_>AkNEWI?egC>vaDN&8Fk`0Da*wf0`!amFy%f-ZE^rom_>Z1;-;Yn{qxw9}=+) z@h<5FeNJK~VRnh0+E95CM-sUvG6cm>{)W4B?Iwc6SmsdO(_Ls8uwA8w#)0K0xrF`W zGvR(JgBuK^n)n(V&B% zWgXqS6GqB)0S}i37OxVg%S5Q4kh!j{@KTKHn^#c6GG#$of;MMFhtpNGnnMMZe0l=> z`t*;!p#mBR`^-i>USyH9af48Mt1BWfJ9SRSF=u?nlu_$LF;`aNo>{8i$)|lH0~Du| zVuuo|0+n;hKu{2QDW1u9`jzE%l6E|RMSq(pw+mQ}O;}2-U(jH7YrKz-v=m0kDO9AG zd&1?)s!44msSHPXnP6{2nvqG7nzYaBusXrwjZg;F)Pa^`V#Z_xPXB^15T5QKXNHLy z-5nS!+7sS6jPDxhwo%?}!kf|N^1dSEK5k(C%Pi7{f?E?O)O7?>Q2qKf0njUA0g zV+{#(#50%Q>y7fUSI4wW`sV)-_9dBWYUhu1;p)qMYyKveX#iDh2K#4a{1`Chd`x z3fei!DX=Wsp&Qi?%H@CJ3`mYA3rcwLA)Ffl2T9W$`e zMZzNn_8Ty4AWUW4Z8m9m%^1W(Zi?0Lzp&8^AfGa$&{Jeui#%&RK&oll_1XF@+gmD} zsK%K;)d2Ip^r)noh-0W2K88l1Qai@8p%JPU4iWesnk3Z#pTg4RYlJ7exek#+u)-}- znIr`$PJE6-2^7!pX|p-;9cl!`p*oxrSb9YXp=6TqxO*&6ns31u&z2R5Pj$;OA8%kq6R?fB<51_3G&C5Avw&$5a3NH3l}65@HBT#OJI0)Mj$k4 zIS6Do0KPwDMbj+V(bR6kv`VnA6i(0C{HEO8k!fUs4P!qutj|bPLW)jRM@(tL;xO@7;lL>C z9B!C;vA8~F1C1Tkj{f$11Fjy1INYHiH z*1?igNU}M2m^Xu9z?W>en)^uz$-qYA#<8E7CuEve(-D7)aK-v9-{nNAUMw>~W6(C= zY3D=q7h-qH&u(V-stmiOs2iV&aL!gF2J6byp0G(1&S9EjIRlWO5l>)fwpOjtra(%F zO&iZgjAfK^q7!+*h@36Nxz+>^4x3GElC&e6OPL6a9E$ZZOHdrh($y))i%is-5*+r) zwEaBU+n#JFTL^mdV zr--P++~J&N-wbf^g0Tk$o^W!d&gI$vR$oj^baQSW_iCsinmGmKtG^U4o5D(rn-t!GJrh*YT=i%z1d! zBzeU7&SXR`7m6Es1?}=lQJR?Y{Z;a4lgyW6=3FOj#gJB6hFMG{#S_5x@3Owro`4rS zNHF?bq4%1LH;6ICNr$U3DLIj9GT0;W+M36msVJ$gh&a}UiOEdNms8yC zVa0>fdqAf+k2WNOhOQ9QurK7;IJ~jY$O`3fC)X5^7RIZe=QO0|y{bsb1o1i6u+i*q zspew{IkO1y8wZ|y+Z+*epL;}P5?JhrSRR;_!|X;l1Xks)XFJxRM~aL@2>Jv-{16SSkO(vmNe%rW2De0Wp@vaKuCR*kplP&0= z-lMzO0XR*myr_5D0@4%7b`s_ORPJO5GePOT9oduS*aDtY;rLumD}=IhUY30VSQ&ia1N^F~|Fb z&wRNL?g<(W+nGu688iIRu{VXqho10RPC~6ysohxD9EXa2A3E3b##$1&vcwWOas-@Z zW@Yluhemp0isJWp#t=-YHLm*;Ybv@$v*9f(i%mQ=?T<7o5j+J1ZK;~fn6h1DgDMI@ zmOt$?w;|=r+F5$eJ>Gz*Ks=bVfZk_yqpTf%Vp0RRiAf6NCGN8bG%~R@=Ui|Bg>vAa zEQ{2Pe_{@}%iM5{OIDqw}R5)cFF$c~pGm=PGa5IuAAWsAD`at|~RpGR1J zIS>s`5^q)y+S@%`wF`OC?tKYnVu^KM+euD)-BT;#r0?Mt8N7}7a7g@u;Mluo4-W(m9}TE`Z4_PfT|=kC6bYe6%J`eV!YDDLCm^H(iT{=}9%d9Qh3)()#eF zr{(g^?jST9ZeZllA}5fNjiZQKkw50qF9aN8L=n4RMC4e+oVm%-PbO7e0)|$WAHLXl zY4qvY^Iooc%Jt^RzvsO?T~jXZ!5%4kVSFOV^?g3ON67!MJBW;nK8)X(2xbP4{|9^{ zj@2>ZGc+wzLm#Ep_HiY6(r2tT9-R^{7~pj&?csNbU~4ne5onA3!Q({F@c9D319E&a zXCmSW_bdCD)lCYDCPkvs`6hgp2)`_XY0tf%su4cd1L57C!&|c#JI7ig$ak=`*={>t z*gAMVLeqS65U253m)^Rjy>E`_I`1Kj)V!7BKAhxg9{E~3n08_U1rt&E&li8&c#*R*NMmN=RR}gG5P81jr(p8Mc$@%RaCen5Pn~bx~y86gaz> zQ2g&J=#7OEb6H({q9S_xum`nUQc*1@z3hij6=;p3K6@@a#7o^9Fd^r`4fElbH;VWW zyoXM4q{3^=wdd5_X`}*^eSsrdX#%UDJ8jnf!V=$$Y1rZ|jU+B1l3i7~p)$xu66By{dAiunRL%#R9?Z zYl(P<_j)5z#I47?yg4gy^50HIZb|GU-k>`tVhnT>v!1pL%83{J+=neBQf`gNmwnKM z7@Ok4@sjLkv^1N2;A+Qos9aCe3TGtYmQN@%zLPO=3(q&Df=pcjNf3r4fwb6|aersq zrbfEQH0+RwcO=A@S<#EzO2)>(j>{VDZ(wkCsU9B z993nY!6FZZPekNx3l8N?Vp4ORXhd~3Yu10fUc^Vk5n{38MqlbU@cJ(V7O4lcn{L=&Ad8zicMCvJBpf$ zcxjCs_m&Z}jYZw#vp%7s>SA^gQdb=cF~=>A0nx-A*h7&`rT&yuI&Bi{*PopCS9PKS zUVk!I5Q7svr=o#5u&3urQLWsQp5tj{Zzf|M!ks8R@Xwt?F2e>UyDCVvoW80VIGWTe zm7*^OlZQT@TZBhBLPe7zG!jxlsh*Lh=zqmwmS)FnGp8MbIIAuAG6X8645kgc*Xu+D@E$_HWlNviQQo($U zroM~O0J=!a{wJ7l;GicUB-o6U2dDVxSnUaNwkXj?{uiFut(X{7cc-VUoGaf*VX>5k zd*xmFZFZF8XRal8s=L(VoV&;gxS|K1d9-zkp~CX-j#kHTWLv??Pq%($nJX6m#g6E5UfZc+#A^wAo2;Y@z6Up+!$pGO%y5F=t21X}%jPgrF}C z$OF5o!Q_Vv-Is{<0RhQHOhInr#`5g*X1v$~lLBvB31rfBVjdu~pGGm)TAVdx9<9q! zFkM}2UGB|MjC!239N@?)=7~X&nr~2RK=bqN8CIp>&<&Y`{@2f#;04}Rkq!??LER>VDbXH=V|L` zl2a?yj}jf09VISD8IgqR)9IHeQ>ApCbQldO0J(-f zCM1XnId8LxtEh>zj#?>>iBEyOxsEc{UGw2dgrlhVG3YnsZ#>_oQMN~|Bb|r4m75E? z-8G}qqtSLvWZ-pNlL)7O6SAF3OQCYXM|-I1igL)cN~m9J680B=6bP;(r*t!cVa{vP| zmE~mK4b0v;1I2!lw3u$xvIr~)<_r)2@up8p1K=}wlU-1$liMD>Z*bQ5}F)grQU~=O&g8QzP zzB1_S#lYIEjIdsYY-wz29uUPK)#?Q!C^UX_&6&3Op3(ysXq7SSaFS) zlX#1{?=<)}P;V~hH##7$M|FB2vwB>Lr5v+Rm%$lk%1(<;vSZV_-Sc{e?d=}H4~+%p zkVL1yJ-kfY(HhfgJQ9wJL$KSOn_EX#!aAgXg~klSPqEz@8iR9`JF~7_P>T7XsXMcF zr+{>aZFz4sjB$;jp2ybi1f6?w;xzEiBSo5vcvhltFK4IL@I|V5hvSWc z<-1oA8iRL1y#=eXymtczhfH_kO70j|nK;DRLSxc?3%j@ebS5c3T$LkPmqLz6V8#Sy~ffZ`-+peOEB*6?vI+MnA+0$p?LON4Z^4KSAU9)0*q|)V7(aqp{{oA zMshkS34B7y*?jlwofwBN#_enHqQMxI+i^ITVeui$cwFq96jCWV6R!$YSof*Td+?+v z&<4e%CBt`)PdQIQaO1oOFK_LzQV>cceL_RvPM%7_X%D2INIE<$O@Tx#WF8eK91*`0 z|KO1GurN`4RR!NU&T;{$3Hj^|cZ*lPJ9N2RjEN4x@)z>hsj4rPpWE+jwRmQ*1~ zZq!yMoXht@E&SVs`sN2A+G~uCXIZ0lmE?!@TuA07ZT+-bhJRYXQ-fIM{Z_{Rc}3Ui z0=m=FV##=^c#<9_iE`36Bv1Bxe}zHp4t)KHZztpxMDs>N1?>}dH`vbX(U{8Q4NI5B zqj@(}m!vQR4m-M3lI`hj4c_X#aWU3FL zJXJ!XQuRH=w$l^h;cF0aeU;o~$txz=lV3Huj!GuVs!3$Y8ySmK_6gq@sfrLAiiNu| z`|H!Q=cGxK@?|vf(%57!(z6N(N%ySk>7b!!g;vvZe57ah&V?1#sYpfMAd;5TeZq+< z38t^@eRUY0*Y@f>tYFwc7oolLdv)%QbI?4t7xxikUQb#2SK}H|EOTvjrZn$6Za(f+ zX)KjDFj10ZhSn$io#J?=^I%miX*z29gm2(`=HXuXSLI*PITUWL-N-b5aL>AfyJx$< zN!wgIx4FKyxo$&q{kG=1-OY7-n(OPE>l>PD8=LF4HP^4<`1*!`U$d2xi<|2ko9j0> z*KKXC+t^(9OovNSrrNsZ+Re?itN0ta>vlEQb4P;9v@UwGxpr}L?X=)#>mEF~Z$)dv z!r;Qrd{Jv{OZOa}`*f}$tziT(8uki49y~m?_TYgv?I2*YuO~Tw#+OPoHP=7UT>nsW z{W_`t!Pckhn(JztYuEFzYWFwSF6E!qZJ9cUvszf>*w)4C1T3vPyyzjx)-Z!XbN$ZN z6_VrNv(I{(sC$fB;e@sg4@!Y&w)0PZ(*Mo%k2Kdk&V8t##ZmHGoc_q>`bC0^tE4>=y0tX?V9aLs&nwW@FphXZ=~Tiq<`N=)k^~*{g%wYne6s@Y1zT zp-qg0`mKU_H_F9c0PUKe5e`h`1io39Jv&5rj|$Qoq{x#}cCS=2RVHqi(AkO(l?fl( zxTU3Onasr66>ZxeDw~4S^D| zAP-HQjtq0d27gCpI9ehQBeIqI@(X9!FMn5gT0^c?E}fahwNVS!Z_Xx_#+H3g9bR=H zXF~JTy0B9fXv2(OqFj$c2?{1?Ud@_Eu2bJ zzM#35y7mayIkhf`1ZuYqxS?gnbQ;>B_0;vX&9!ry>t;*+%bV*SqFy--HP=!+6`jS^ zde*=$>EVp#`qea8Dnk9_Y;|*mz0YY`IFIOphOJ$t{%F!F;eOP_Qm)@moewtGQKK^s z?w;E6?0Q2r!jLF`-5gWAQ5clbuzShWuc zW6dFtc_jj;SWo3sj&RhrV{Y5SPtmN=QfZyPF0d_`npI4zTv@%exkYK`Gh+9c1`!G- z>Dt|&an6D=s-(JC@Ik$p#ht2qM%cHDA8RMd#%wOKv|6cO&hi820In1Pcs(5Ko8f>S7ya) zSOhKiOJ>-TAnk;LLK~~JUmV)_RLg>`X1}n6dPpxfPIITTO=RVCeOutbw z1Xaa5`DRNna=GCV>u+8BSj(0r!crO;g(RibukJ{rm{vkx+q5;ZJ#Ll_wuz;ZZ5vys zEy&(EKLb+!Zy@6T;lbx%HUDR@khAjtQFPeL80$x`hCn4$VTj9ZmU8P!w6l)GRET4? zwMUjdt>k&!Y8?%DhFA-%Vb4845~Y_hZw>opwH&xSxbJ|=Mh?x~+%o48ZjBqKF06Mp zVXxe=RO)Jg+!<<}HRo808Gh`W5J&cEWY&k-wg|g*>wFsj!2^%VWJ2yG_O_83ys}4+ zxU@xBq7l_UZnThK@BIEDbc}kRh7D{yNqj5g$61Rg5ZZ zE^1mO;s>wf!^@U;p#MxF+eFB&?nFpVRV)@)kc3?W_xR}^I@Kk zoX@*Y1?6s?b>PtEc_I3DXyab9&os4?w!s2yPzhuea}#YLi#2SbSy$NP>@S{rL$39y zW$mKF^&7L9wU_Ur;#4;H|%6GdfY-*$z|pi3ZLJL?Nly4~L>OMo>|@UtrZHn4 zD+6lam}wM_XB-Pv$b+leCg)8IM?DGWg<+>XxO*P$VIfiNL?Qt~+u6s0>BLvS32zgM zY&2ZJ!{N6cTEAIj3z0UA(IwMF^{>#aa&ew^w^=M)`F{TH3;+8%EZ<%gZ>_R zmbr|pg3(s4xNTDQMoePCqUO5U#NkA)lI^~BYgRvXh>O`YR{yw{+^7yQw)Fw)eMmYF z8OUt1yr!OUGKL%uleH~V$7W3>5*LNhWXF>o9!F63pgyoGR{xiV`-DSUQOi^7TDNQu zv`ubc=3{ynbZ%fOZfe~@$#a8qWtocST4uJTS@NvOAPx=7qD#zEk(CS){>+BQF92yVI0wQFsJy;upd82oHJK z_UVm$5~CZA+Q^Lcs!CIfiFDNLv-CB%g7PMVxjr1E%UY?+&xEU zLDoxmPmz#)0^r$cTjxC3vT*(TdmB>vAmsadXE}yeZm4lTB}S_F2S+6F;GT6P)dWzk z@XWxaKoiya)Uzyytgmg|@>sT2O)w%jZkxTcbvg}X19iB$b_rqk{k_XV4qq@wH&a7Q z$2@|SEpwl3X_zVevdJeLv7oto>Y?=;tb?BH3_Slr3-;vA^_;D!B>3Q=O_X^lWo~;! z_6VK(6>Z|JU`^M_y`;m@cf$pi)b{&Za^OVP8CDqchboJYSgNcsU5{6Ks zRryU)$5M&+P~~W9aL>_wo1#|jvzi>^7=usPj~40v^R8p+O3tIG4%U{lvZL%yww2ze zg^}#xYGKEUB5PwehD$AwZJjdA3;Gc2lW<9Br`fgz`$aQrvYl6gjOZQcyldPzmbtJ? zA64s~`OH2!G3Yb0mmiO;)%wpFavUr$tACi;k!Zr%lV#V^Xbr#;9ayM7LhT+4wPV6_ z8~1VatT8hwII3}WtvO{+HAXnea`QawCLDfrrJhyz5`tsf_sa3_WLb@u`D^np3}cQH zvr{`b{=BNy>FkL7H~iduy&QCW>Uy7oF5jDsUJN2*ay z^m3ZHcx#y}yazJI3^LVaeU2MlV61ykF7_}8<7%M|(ZsYat#h3~d@cpX3@U4iSCjXI zF8f%#DbPb8lwA;OCgfQa&e1-LI9bZ+)LQB#iJ-<>on_&hT0261wolISHZhldcol5O za*#u;{cu~&Ix@{_fJLskGXw6C2DcDW z_nKgTQ7^lwGqLT;6}gfFgogIyfsP6umb;{vw^@6k!Iz0Lu6>p?Eh|3T6Gm6DHYMEA zj_Clq3e4zr`PCd-J<>goXNhcOv$BkTqCVFi5OKc2920MTqIJpqP}}m|t+Rr}(v}5l zW%F@XzSA>h<+eS!33~G3<)ncx&W&L!lXZOJRU!^;+Sa!HNt-C_k!*Baoedw19nkUk*9kRwcKxP6A=WD0V#_bhY}h^FLT@y4Pbe9*<4iqyac zS9ck@M>7F^aATdKN4?^6`I-f4)<+X-OhnMCbtlbHLEENh0~n0Y)EUCAW4q}E5V_Yv zZ&k54_rl1ss)p>BrbOu7YAlZ1?6u)9R>3bN%8k>bDCE;x_>!ql;mIC_V;Aw2N6Z8CG~ zgIh$DeL(F!x$fGnGM?xj50lW>vSl%@E7)f8BWK9=3&DQLD}DO9mf6b#kA3F%N3gN=-QRHa;9rQ>CS*T}I~ z5HQb2RaqAC9%Jdx){lWlc*Fs}YVPrY2)LDWEHjUj_+u&Qaa0Mg#k$ve+B^7Rp8V7! zhZoHW`J4knEo-0R{RJ*o=7`R#X7DZ>;9nJLowKH8?+)Mg5gdC&5#L?aj*^b6JF8QgPYc2l?_bi-kJbb3PS6vA_ zNAp>dm&+=rBBvPWj89kgQ9kY%8erYT-Ro$Qwmz`o(1Cr2cCE29ZiOkjJ$rl0-d!yX zJ8juB+ryHVp*s3C8TE|v&k+sHRb@m2wC#ZYJE3NEI&-~IZniv{WkB3;gd-MKR_F35 zzP~x^MxQpZUwt7x-WQAQK8M)Y&vdZW(HL3|EP>6Z?~xL%tI%GX2psV?qMvOWn{X}8 zOtIfx%Q`GrIL{lNULQcx-nP^v6J$^F_Aux1RnB2_(7tZ`q;i+FTd+urhUc{fhiq$Y zh##NC4Cv=VW!^BnvJ*zb6Cy-Fl5iw-7QZD1T0-lJReX61nl$nJmJM^@QzS-&+PTJT z8sI--J?fy2du>fKTW3wpI=5LbmxnS+OqShl`bNeGfa`wQzG1kvVGmQ#;AFC_A{Oq)KhVxUOCiIPEyKL4 z%kMbKbv@m+-Bqmq$k-QMH%W^(=DyHudD9@IMTfZF07G7tGubx2m?8qsgAj65+!K? zKHJ(Wm6|Wd^5M#Pmc*w7JwrE0|Ngz(ID0t8RP(w5Q|mNb18tl23h*3`j$kI3r>b6k}ChQ#O2fah$-Fnp5-D@>9@@Gd+ zEbHWmkvZo!wtTiN-3J$wL+clX-0O>3TW~mD$xly(106^_KD6yVQz0Bp?;~yoA&AV@ zD0F13^H5jno{=If*S9v!aXE$K8139T4m>u1*Gf>e<{Fmw1j$LQdyqDFB?=-3&s7ZX zE_Zn9vXN7d+^}3&irh>@0YaWL=rG zke=k0sB^WA*#_2td!J5SK&e?eyl(mzcy};s254bVt-UlA4OhienHuH2Jfw$MbXxd8 zb1nVfh>pp201B^ znQ#r0oMv+}Z2~M&_OdLInwXNu0hG_|V47`dSlo?&GBA=ZiO0LEifL4l%|6#=XIPG5 zILy0ow{-WO>4}L;^gApwS>QcV_gZ8N^hw5Kh4oIO)2i_!5H`Y7zt?H_yIttBW%<)s z8zQ4fg$H-fYu)m=SgM2VHli6rfA%~oa8%A~L0UljWjfB(yiY2)+r4w;$BN4`A=^n_ z`MqrwiMtE<1rgy3Z97&5igAY@*+m~}f)|FRz7sw#goaIlH#VG0#CsK}A%chAsC6)R z5+f07^w1Wk8h%C8`&hTJ-Gyg7ELb5N&+3-nU0pm3YP;oe3~hZxxw#bNkdYsamyL2& zaS&wBbNDiwgM*OK?`P_<2osIh`J{ElR8eJ&a#F`9BU9UU)Y;e6jlT|Y%`J=FB01}F zFB;~o3kgsw*iXx?`_O?0eBH5Bu&i5f?jFrn7UNhSvNa)dFT|Q|b-(v&Oqwqsiuft1 zYzja^ZOeD_;~C&ZEdQ(x=jY2=E)La%4QX<_$2YmIm{~T9j^*-c%v-DzE#|SiJy9m0 zS6@O|nuEwYycMi8$7!UtEjc{*=^$@Bzd)J0*ug!sg-0#)zJj1tS{=-FL)H7zK#m)# zIXxw^n3+?Z*NxYaRRd(_mWD@LmanuoY1}kti(KutECTf%ljgLcD7O?7cGJN!%!WWZqtm>?X2uSR0}3WBHgGrktWaBcfHMN7l@l5atWu!sG2MK{_K4 zW|Jo#Uk$ZBvF1p=p}eOo4#^y>_G{Z&bjj}!gpH%rTqCUp-P3emVF{*q{~LTEXK&UX z8HG$e9gR+vRW8T9v+R5rVUCNkS-p`HsDK1hjpJ1|*V@|m2VGcI%x-Kp4`Bw?>OYcd zH%H*;aAE<;L2|TTfQ6Nr=He}1xoT?XM)pdAO=XjLKyg!7C$f(>^;Bw&I7pr?f)`N4fl4!7{VMfcWr=@|-dPhcO`g-WX z_Nglz@Y!CV`?KonrfN(1u>AHn^tKxJ)Q7hk**GWLV}mpbPrjwf>g;ElsL>9--|Bli zEO6b+m6r}yXB+uE_bmchvd=*E{@!KYE960r0<}$S^&L}mr(@a4aZ+l?Qs>vYIPu{LW^5)omU9K=*#JiX=hz2JZGy27@K5kd%_$exTieCj%ew$Et|%> zoQl9I!OCOp8_X8F(Fh$6m?ylQEjvfsp_ZBJX&LFW7M2qk?}XD%p(e59z(%{4&Ghu8_O;G7whXwN4(TLHMlzY zVSwCEQ<&E&8ej<4aC^5^tzt*I)N1?&vK|;|v`&%K0LQO`oxuhaW2!qJGG4Sol_; z?P37*5ME(A=sbQ=q<({(ws-dJ#s`62&_d(_;6&(1Ku zC%A?=RTheIZucs^xi6sPy0G649hs+Yvw2tti)CF^%w5d!`LGU3I?&0$CwM$wc>Xl? zEX=0Uqg&(lI~uNfg)?MN)*KI)92=HoHrbkD9@K5;x%S7ipI|k8_CKoo|4`Q)C2oV? z=hCj-oun*AkQ3iN7xZ?IO^;0RSp|*)Rsa9lYg!i0^D)Ve^1)-@u{w&$Tss?n^dRUu zRF-YPb(;u&yEM3FSGUZnAO}ZdG#V^s`-isMs;69sk)MN9xPA}zegCkrk-^Hk**HjhJQTC< zVtF;rrlQd|2WXi7XKUBza*?o%;_yecZ@$fC^NqSy2VTsl0s0gVzYOO)6p%v3oZik8 zasdY4BP5$8W#zJG(*9jg|C`c&_CeR}r1mv8G%x!zpM=y@+QpD7okBz|>fvw76U^W22`hSbf`8#T3C zN!>lPkzLgfPo+M=34dvy&f#PH@BgcNILF*y!6bcTxgmMx^4RPD>^EnQy=|ci8C#Yz z*fdwn51VmL@!6V)N2dfd5iS_OGgeZOOvLhvYx3gJu$fltsad`L7wGY+X#g!-_aAy{ zjr|avuR%F=HnrtWGhW>wD#u$$V%v5sY+bp61#^ALJy<&Nyw`?;QSII7Nc|o`rko{% zC*`)c8}&vFZOX#bTEDe9$CHrlpFO(=mQL$4jI`o<+M6`b#Xck0u*I4`L?Ji(i(uU~ zxLP+$WHzklBki*d_wuK0+6ee1l19ge!C9OwTNbKOGxz(grgr6cfnL4F3&MV~buO;t zxCeU9@t!+NQQA*R<|?n15cR^nteC+kkp4&Tx|+5&aio%3#@4Ue|2Smj52 zt^YUHk5EhNim9y5b+{Jmw+j77NbU>h?yDb1T_EQ#&HH{7+W*79CR3d#-5WKm4v9{B zZXbXq`$naod~Lt!u)Q*lzN-J-+_m&JbwuG=_g7pYA;BVrw!17)tG0_uZG}oD7Ey#C zF-@c-j^YGVA*48@h=+rDG^F&Uij>C0#a2rzD6jsQBu@Dkz2`AAXP!2Zkk}BeJu|*{ zX70?HbH4L^;h`S}p@nBPZ0?Y~$9OYhJ?tCd^xmXosMD4+c{RPiFq2V42yI}Kby6Y^ z&W=_8sU>WW4kX2i6URhXCJGE4DgS&d%9&JG@mP|3$BxaT7P81}@`S2)^bOHLubg^o zB(=*7Di-A4z%-q!!gL5}G@vI4Bw~P%3{c6eio2_uJIzP-R&X2P|Ht<`KcZ)^SwLEk zYxsr!h_m1I#W$_(=eLybfa~YZ0sj@wlJ9Zw*SD-BSkm|-Fu6nF3Lg<8MsMw2F{DT+ zh5ZD{2AQre&tbIFyoSV;FnOfkVYpDUDbB{FP|20v zHR2`?iHEz1DHQ|dqlvq$q}WZlBbA$7LyJMVG_J&pY=ok0MnAnQiZiL`556DtfiPE* zW9ahzElcQ|VA1;YqYsYa?hjA%;pbZ{AWqO&0Sx`)=iVaFI%roa`yz{>0(mhS;A7e6 zIYS`Azw(qH`SOlLR_J>D(MSl@o%}ClGAs9^2`+XkvE8>bu{20UCLyR_gmg-W_trKF5qBnSU zqFSv@V9+BeOd95@q_vY|+yxPH8LDtcRWzwz#QD-ZkL*hl7Yyy!_7chldc6IEH!n;) zHokS@6D~)BhT(=z{z+4#O9~!GLBg_k*d=TC&XZoVW5LkmZC|Vl|1RYP3rD4U9*Yg| z&czjhX7`*e;Z`JKR0ZZbbrazaITn4xq$b9bik2qY5rff!Fr7oTh{Gdk-~{!D4psOf zh`?wB)GnL7+yC?)u4>`G(}_UX`XjU1p$B#luPC<*%%ab_FlN-q-EBS8=U%b za#l%?p5m}4EcXvn=_>wH@&%*WKB1GRPx(S598^!w&gas@~ z;cds1fGuOE{wmxy4n{v;kEkrGbG0o?7?i+}#c7)@Uu9m@EDO-=UnfMY#p~oJ8`b&S zs}tyzd8jSN8z2Gm#FOG8`5khXET>Dqc3m+4-r7w*h=&e_sU;A?IXqHotolF!)@sOnyh%yW|yLGyO%HFDZDBP=~U5z)j>*s=@F^6fmSU0qSupqBCA&pzo)_S?x$1A7Q zarTsSq6u6M0^`XgJUFz;Co8R($CxRX5mO#Ks-Lm*Xw~hH#ee$U_Ty_7{su3$z}u2$ zLSP2#)05^kv1e(Ubgd{Slxag9dU6Rw-4O1Fh7=FPxnaeZtOt-&Vf|wU9jVsvjOr3L zM!h)ErooD$sAc33)4^_x$f$+f!4Uz;plF7NteZM6U>CRO+(~O^xiysAO7Hhy1d=z_ zV)W0ygwXR+7*7bNs&r(c zHk!^>rKP%D8Iaq}^S~w9yB#kY%s8^SiQB**xDAq2N$mgGago2_MaYAcc!?6JTY(vu z;mNH-AyYV~?rz)^Zh&~kUAQ-Tc~#-pcGHQg`#_hzD8KzR(K+E}oU?qx-^XFW2Sa{M zO^fWz470!6DdKMQ!~1J#_Pf2(+(dDTz5;waaWuo!B9%2##5^xy+q)ufVo+ym;AoZc zyMcYJYUH!Z%=~0^W;6-<9FfSeRIz${M9%rqsK?CP+4@##kA#Ax5>F6TDesn+u2JQN zys(pUg`J%s@wv0yiZVg7w3EEjS0-d2oSoSDK|Cq!6k?5}!zLfEPJU zod->MGg*yIOjpO1oSE*0rvc3l)Z*OX^TWltcg`b603J`Y-tcd*k(Q?I(h9FFWI2#z z0#n$p-Lr&e#V1D<@{%xM6} zQgYFr^zBf8j`n9QM(6PxxoT(}Uypw0YnVGOS8?&$eqbFt@?Yp&pa8#f-C23isZvvr zt}{{_Ef(gcKyq-rI9;79#;c%3I9Hjj&Q}T$qpiIiNNSYU!1mL7?jTJ{vCsl%qY zuGJe}C`JRPEIWV zk8@iul6$p_gN=?^aq-W79F^T4I?A}L1T7)R_;`!U?9|Ef4NenzMcK0)N*}N9nK8%E zsMr{@zdYwo`AQl`BBDoZPyR#r*CghsY7^D7YX5j~s3`yOyGoE28$m0stlr5h)ixNe$uvIC7egG5&VZl+}J=$5BQ~ rCKvE{^IWz4J+Z}L&iO+Fl~M-NxBYw-MTgK%KrBui?L(kh@|XP&0kbf? diff --git a/rhodecode/i18n/ja/LC_MESSAGES/rhodecode.po b/kallithea/i18n/ja/LC_MESSAGES/kallithea.po rename from rhodecode/i18n/ja/LC_MESSAGES/rhodecode.po rename to kallithea/i18n/ja/LC_MESSAGES/kallithea.po --- a/rhodecode/i18n/ja/LC_MESSAGES/rhodecode.po +++ b/kallithea/i18n/ja/LC_MESSAGES/kallithea.po @@ -1,4642 +1,5658 @@ -# Translations template for RhodeCode. -# Copyright (C) 2013 Marcin Kuzminski RhodeCode -# This file is distributed under the same license as the RhodeCode project. +# Japanese translations for Kallithea. +# Copyright (C) 2014 RhodeCode GmbH, and others. +# This file is distributed under the same license as the Kallithea project. # Translators: -# しろう <>, 2013 +# しろう, 2013 +# shirou - しろう, 2013 # FIRST AUTHOR , 2011 +# こいんとす , 2013 # Takumi IINO , 2013 +# whosaysni , 2014 msgid "" msgstr "" -"Project-Id-Version: RhodeCode\n" -"Report-Msgid-Bugs-To: marcin@maq.io\n" -"POT-Creation-Date: 2013-06-05 19:55+0200\n" -"PO-Revision-Date: 2013-06-05 07:39+0000\n" -"Last-Translator: Takumi IINO \n" -"Language-Team: Japanese (http://www.transifex.com/projects/p/RhodeCode/language/ja/)\n" +"Project-Id-Version: Kallithea\n" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" +"PO-Revision-Date: 2014-02-13 14:34+0000\n" +"Last-Translator: marcinkuzminski \n" +"Language-Team: Japanese " +"(http://www.transifex.com/projects/p/Kallithea/language/ja/)\n" +"Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -"Language: ja\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: rhodecode/controllers/changelog.py:149 + +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 +msgid "There are no changesets yet" +msgstr "まだチェンジセットがありません" + +#: kallithea/controllers/changelog.py:186 msgid "All Branches" msgstr "すべてのブランチ" -#: rhodecode/controllers/changeset.py:84 +#: kallithea/controllers/changelog.py:189 +msgid "(closed)" +msgstr "(閉鎖済み)" + +#: kallithea/controllers/changeset.py:87 msgid "Show white space" msgstr "空白を表示" -#: rhodecode/controllers/changeset.py:91 rhodecode/controllers/changeset.py:98 +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 msgid "Ignore white space" msgstr "空白を無視" -#: rhodecode/controllers/changeset.py:164 -#, python-format -msgid "%s line context" -msgstr "" - -#: rhodecode/controllers/changeset.py:345 -#: rhodecode/controllers/pullrequests.py:478 +#: kallithea/controllers/changeset.py:167 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "diff コンテキストを %(num)s 行増やす" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "お探しのリビジョンはこのリポジトリにはありません" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 #, python-format msgid "Status change -> %s" msgstr "ステータス変更 -> %s" -#: rhodecode/controllers/changeset.py:376 +#: kallithea/controllers/changeset.py:386 msgid "" -"Changing status on a changeset associated with a closed pull request is not " -"allowed" +"Changing status on a changeset associated with a closed pull request is " +"not allowed" msgstr "クローズしたプルリクエストに関連するチェンジセットのステータスを変更することは許可されていません" -#: rhodecode/controllers/compare.py:74 -#: rhodecode/controllers/pullrequests.py:256 -msgid "There are no changesets yet" -msgstr "まだ変更がありません" - -#: rhodecode/controllers/error.py:69 +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +msgid "Select changeset" +msgstr "リビジョンを選択" + +#: kallithea/controllers/error.py:72 msgid "Home page" msgstr "ホームページ" -#: rhodecode/controllers/error.py:98 -msgid "" -"The request could not be understood by the server due to malformed syntax." -msgstr "形式が間違っているため、サーバーはリクエストを処理出来ませんでした" - -#: rhodecode/controllers/error.py:101 +#: kallithea/controllers/error.py:101 +msgid "The request could not be understood by the server due to malformed syntax." +msgstr "形式が間違っているため、サーバーはリクエストを処理できませんでした" + +#: kallithea/controllers/error.py:104 msgid "Unauthorized access to resource" msgstr "リソースにアクセスする権限がありません" -#: rhodecode/controllers/error.py:103 +#: kallithea/controllers/error.py:106 msgid "You don't have permission to view this page" msgstr "このページを閲覧する権限がありません" -#: rhodecode/controllers/error.py:105 +#: kallithea/controllers/error.py:108 msgid "The resource could not be found" msgstr "リソースが見つかりません" -#: rhodecode/controllers/error.py:107 +#: kallithea/controllers/error.py:110 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." msgstr "サーバーが不正な状態になったため、リクエストに答えることができませんでした。" -#: rhodecode/controllers/feed.py:52 +#: kallithea/controllers/feed.py:55 #, python-format msgid "Changes on %s repository" msgstr "%s リポジトリでの変更" -#: rhodecode/controllers/feed.py:53 +#: kallithea/controllers/feed.py:56 #, python-format msgid "%s %s feed" msgstr "%s %s フィード" -#: rhodecode/controllers/feed.py:86 -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Changeset was too big and was cut off..." msgstr "チェンジセットが大きすぎるため、省略しました" -#: rhodecode/controllers/feed.py:90 +#: kallithea/controllers/feed.py:93 #, python-format msgid "%s committed on %s" -msgstr "%s コミット %s" - -#: rhodecode/controllers/files.py:89 +msgstr "%s が %s にコミット" + +#: kallithea/controllers/files.py:92 msgid "Click here to add new file" msgstr "新しいファイルを追加" -#: rhodecode/controllers/files.py:90 -#, python-format -msgid "There are no files yet %s" -msgstr "まだファイルがありません %s" - -#: rhodecode/controllers/files.py:271 rhodecode/controllers/files.py:339 +#: kallithea/controllers/files.py:93 +#, python-format +msgid "There are no files yet. %s" +msgstr "まだファイルがありません。 %s" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 #, python-format msgid "This repository is has been locked by %s on %s" msgstr "このリポジトリは %s によって %s にロックされました" -#: rhodecode/controllers/files.py:283 +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "有効なブランチ上のリビジョンからしかファイルを削除できません" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "Kallithea経由で %s を削除" + +#: kallithea/controllers/files.py:346 +#, python-format +msgid "Successfully deleted file %s" +msgstr "%s ファイルの削除に成功しました" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "コミット中にエラーが発生しました" + +#: kallithea/controllers/files.py:373 msgid "You can only edit files with revision being a valid branch " -msgstr "" - -#: rhodecode/controllers/files.py:297 -#, python-format -msgid "Edited file %s via RhodeCode" -msgstr "RhodeCode経由で %s を変更" - -#: rhodecode/controllers/files.py:313 +msgstr "有効なブランチを示すリビジョンでのみファイルを編集できます。" + +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "Kallithea経由で %s を変更" + +#: kallithea/controllers/files.py:403 msgid "No changes" msgstr "変更点なし" -#: rhodecode/controllers/files.py:322 rhodecode/controllers/files.py:394 +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 #, python-format msgid "Successfully committed to %s" msgstr "%s へのコミットが成功しました" -#: rhodecode/controllers/files.py:327 rhodecode/controllers/files.py:405 -msgid "Error occurred during commit" -msgstr "コミット中にエラーが発生しました" - -#: rhodecode/controllers/files.py:351 -msgid "Added file via RhodeCode" -msgstr "RhodeCode経由でファイルを追加" - -#: rhodecode/controllers/files.py:368 +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "Kallithea経由でファイルを追加" + +#: kallithea/controllers/files.py:461 msgid "No content" msgstr "内容がありません" -#: rhodecode/controllers/files.py:372 +#: kallithea/controllers/files.py:465 msgid "No filename" msgstr "ファイル名がありません" -#: rhodecode/controllers/files.py:397 +#: kallithea/controllers/files.py:490 msgid "Location must be relative path and must not contain .. in path" msgstr "場所には相対パスかつ .. を含まないパスを入力してください" -#: rhodecode/controllers/files.py:431 +#: kallithea/controllers/files.py:524 msgid "Downloads disabled" msgstr "ダウンロードは無効化されています" -#: rhodecode/controllers/files.py:442 +#: kallithea/controllers/files.py:535 #, python-format msgid "Unknown revision %s" msgstr "%s は未知のリビジョンです" -#: rhodecode/controllers/files.py:444 +#: kallithea/controllers/files.py:537 msgid "Empty repository" msgstr "空のリポジトリ" -#: rhodecode/controllers/files.py:446 +#: kallithea/controllers/files.py:539 msgid "Unknown archive type" msgstr "未知のアーカイブ種別です" -#: rhodecode/controllers/files.py:631 -#: rhodecode/templates/changeset/changeset_range.html:9 -#: rhodecode/templates/email_templates/pull_request.html:12 -#: rhodecode/templates/pullrequests/pullrequest.html:124 +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 msgid "Changesets" msgstr "チェンジセット" -#: rhodecode/controllers/files.py:632 -#: rhodecode/controllers/pullrequests.py:149 -#: rhodecode/controllers/summary.py:76 rhodecode/model/scm.py:682 -#: rhodecode/templates/switch_to_list.html:3 -#: rhodecode/templates/branches/branches.html:10 +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 msgid "Branches" msgstr "ブランチ" -#: rhodecode/controllers/files.py:633 -#: rhodecode/controllers/pullrequests.py:150 -#: rhodecode/controllers/summary.py:77 rhodecode/model/scm.py:693 -#: rhodecode/templates/switch_to_list.html:15 -#: rhodecode/templates/tags/tags.html:10 +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 msgid "Tags" msgstr "タグ" -#: rhodecode/controllers/forks.py:176 -#, python-format -msgid "Forked repository %s as %s" -msgstr "リポジトリ %s を %s としてフォークしました" - -#: rhodecode/controllers/forks.py:190 +#: kallithea/controllers/forks.py:191 #, python-format msgid "An error occurred during repository forking %s" msgstr "リポジトリ %s のフォーク中にエラーが発生しました" -#: rhodecode/controllers/journal.py:110 rhodecode/controllers/journal.py:153 +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "グループ" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "リポジトリ" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "ブランチ" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "タグ" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "ブックマーク" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 msgid "public journal" msgstr "公開ジャーナル" -#: rhodecode/controllers/journal.py:114 rhodecode/controllers/journal.py:157 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 msgid "journal" msgstr "ジャーナル" -#: rhodecode/controllers/login.py:138 -msgid "You have successfully registered into RhodeCode" -msgstr "RhodeCodeへの登録を受け付けました" - -#: rhodecode/controllers/login.py:159 +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "キャプチャが一致しません" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" +msgstr "Kallitheaへの登録を受け付けました" + +#: kallithea/controllers/login.py:237 msgid "Your password reset link was sent" msgstr "パスワードリセットのリンクを送信しました" -#: rhodecode/controllers/login.py:179 +#: kallithea/controllers/login.py:257 msgid "" -"Your password reset was successful, new password has been sent to your email" -msgstr "パスワードをリセットしました。新しいパスワードをあなたのメールアドレスに送りました" - -#: rhodecode/controllers/pullrequests.py:136 -#: rhodecode/templates/changeset/changeset.html:10 -#: rhodecode/templates/email_templates/changeset_comment.html:8 +"Your password reset was successful, new password has been sent to your " +"email" +msgstr "パスワードをリセットに成功しました。新しいパスワードをあなたのメールアドレスに送りました" + +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 msgid "Changeset" msgstr "チェンジセット" -#: rhodecode/controllers/pullrequests.py:146 +#: kallithea/controllers/pullrequests.py:157 msgid "Special" -msgstr "" - -#: rhodecode/controllers/pullrequests.py:147 +msgstr "スペシャル" + +#: kallithea/controllers/pullrequests.py:158 msgid "Peer branches" msgstr "相手のブランチ" -#: rhodecode/controllers/pullrequests.py:148 rhodecode/model/scm.py:688 -#: rhodecode/templates/switch_to_list.html:28 -#: rhodecode/templates/bookmarks/bookmarks.html:10 +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 msgid "Bookmarks" msgstr "ブックマーク" -#: rhodecode/controllers/pullrequests.py:321 +#: kallithea/controllers/pullrequests.py:330 msgid "Pull request requires a title with min. 3 chars" msgstr "プルリクエストには3文字以上のタイトルが必要です" -#: rhodecode/controllers/pullrequests.py:323 -msgid "Error creating pull request" -msgstr "プルリクエストの作成中にエラーが発生しました" - -#: rhodecode/controllers/pullrequests.py:343 +#: kallithea/controllers/pullrequests.py:332 +#, python-format +msgid "Error creating pull request: %s" +msgstr "プルリクエスト作成中にエラーが発生しました: %s" + +#: kallithea/controllers/pullrequests.py:354 msgid "Successfully opened new pull request" -msgstr "新しいプルリクエストを作成しました" - -#: rhodecode/controllers/pullrequests.py:346 +msgstr "新しいプルリクエストの作成に成功しました" + +#: kallithea/controllers/pullrequests.py:357 msgid "Error occurred during sending pull request" msgstr "プルリクエストの作成中にエラーが発生しました" -#: rhodecode/controllers/pullrequests.py:385 +#: kallithea/controllers/pullrequests.py:397 msgid "Successfully deleted pull request" -msgstr "プルリクエストを削除しました" - -#: rhodecode/controllers/pullrequests.py:481 +msgstr "プルリクエストの削除に成功しました" + +#: kallithea/controllers/pullrequests.py:485 msgid "Closing with" -msgstr "" - -#: rhodecode/controllers/pullrequests.py:518 -msgid "" -"Closing pull request on other statuses than rejected or approved forbidden" -msgstr "" - -#: rhodecode/controllers/search.py:132 +msgstr "この状態で閉じる:" + +#: kallithea/controllers/pullrequests.py:522 +msgid "Closing pull request on other statuses than rejected or approved forbidden" +msgstr "拒否(rejected)または承諾(approved)以外のステータスでのプルリクエスト解決は禁止されています。" + +#: kallithea/controllers/search.py:135 msgid "Invalid search query. Try quoting it." msgstr "無効な検索クエリーです。\\\"で囲んで下さい" -#: rhodecode/controllers/search.py:137 +#: kallithea/controllers/search.py:140 msgid "There is no index to search in. Please run whoosh indexer" msgstr "検索するためのインデックスがありません。whooshでインデックスを作成して下さい" -#: rhodecode/controllers/search.py:141 +#: kallithea/controllers/search.py:144 msgid "An error occurred during this search operation" -msgstr "検索を実行する際にエラーがおきました" - -#: rhodecode/controllers/summary.py:182 +msgstr "検索を実行する際にエラーが発生しました" + +#: kallithea/controllers/summary.py:203 msgid "No data loaded yet" msgstr "まだデータが読み込まれていません" -#: rhodecode/controllers/summary.py:188 -#: rhodecode/templates/summary/summary.html:149 +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 msgid "Statistics are disabled for this repository" msgstr "このリポジトリの統計は無効化されています" -#: rhodecode/controllers/admin/defaults.py:96 +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "認証設定の更新に成功しました" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "認証設定の更新中にエラーが発生しました" + +#: kallithea/controllers/admin/defaults.py:97 msgid "Default settings updated successfully" -msgstr "デフォルト設定を更新しました" - -#: rhodecode/controllers/admin/defaults.py:110 +msgstr "デフォルト設定の更新に成功しました" + +#: kallithea/controllers/admin/defaults.py:111 msgid "Error occurred during update of defaults" msgstr "デフォルト設定の更新中にエラーが発生しました" -#: rhodecode/controllers/admin/gists.py:56 +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 msgid "forever" -msgstr "" - -#: rhodecode/controllers/admin/gists.py:57 +msgstr "無期限" + +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 msgid "5 minutes" -msgstr "" - -#: rhodecode/controllers/admin/gists.py:58 +msgstr "5 分" + +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 msgid "1 hour" -msgstr "" - -#: rhodecode/controllers/admin/gists.py:59 +msgstr "1 時間" + +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 msgid "1 day" -msgstr "" - -#: rhodecode/controllers/admin/gists.py:60 +msgstr "1 日" + +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 msgid "1 month" -msgstr "" - -#: rhodecode/controllers/admin/gists.py:62 +msgstr "1 ヶ月" + +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 msgid "Lifetime" -msgstr "" - -#: rhodecode/controllers/admin/gists.py:127 +msgstr "有効期間" + +#: kallithea/controllers/admin/gists.py:147 msgid "Error occurred during gist creation" -msgstr "" - -#: rhodecode/controllers/admin/gists.py:165 +msgstr "gist の作成中にエラーが発生しました" + +#: kallithea/controllers/admin/gists.py:185 #, python-format msgid "Deleted gist %s" +msgstr "gist %s を削除しました" + +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "変更なし" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "Gist の内容を更新しました" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "Gist データを更新しました" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "Gist %s の更新中にエラーが発生しました" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "このユーザーを編集できません。このユーザーはアプリケーションにとって必要不可欠です。" + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "アカウントの更新に成功しました" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "ユーザー %s の更新中にエラーが発生しました" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:50 -msgid "BASE" -msgstr "BASE" - -#: rhodecode/controllers/admin/ldap_settings.py:51 -msgid "ONELEVEL" -msgstr "ONELEVEL" - -#: rhodecode/controllers/admin/ldap_settings.py:52 -msgid "SUBTREE" -msgstr "SUBTREE" - -#: rhodecode/controllers/admin/ldap_settings.py:56 -msgid "NEVER" -msgstr "NEVER" - -#: rhodecode/controllers/admin/ldap_settings.py:57 -msgid "ALLOW" -msgstr "ALLOW" - -#: rhodecode/controllers/admin/ldap_settings.py:58 -msgid "TRY" -msgstr "TRY" - -#: rhodecode/controllers/admin/ldap_settings.py:59 -msgid "DEMAND" -msgstr "DEMAND" - -#: rhodecode/controllers/admin/ldap_settings.py:60 -msgid "HARD" -msgstr "HARD" - -#: rhodecode/controllers/admin/ldap_settings.py:64 -msgid "No encryption" -msgstr "暗号化なし" - -#: rhodecode/controllers/admin/ldap_settings.py:65 -msgid "LDAPS connection" -msgstr "LDAPS接続" - -#: rhodecode/controllers/admin/ldap_settings.py:66 -msgid "START_TLS on LDAP connection" -msgstr "LDAP接続でSTART_TLSを使用" - -#: rhodecode/controllers/admin/ldap_settings.py:124 -msgid "LDAP settings updated successfully" -msgstr "LDAP設定を更新しました" - -#: rhodecode/controllers/admin/ldap_settings.py:128 -msgid "Unable to activate ldap. The \"python-ldap\" library is missing." -msgstr "LDAPを有効にできませんでした。\"python-ldap\"ライブラリがありません。" - -#: rhodecode/controllers/admin/ldap_settings.py:145 -msgid "Error occurred during update of ldap settings" -msgstr "LDAP設定の更新中にエラーが発生しました" - -#: rhodecode/controllers/admin/permissions.py:58 -#: rhodecode/controllers/admin/permissions.py:62 -#: rhodecode/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "ユーザーにメールアドレス %s を追加しました" + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "メールの保存時にエラーが発生しました" + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "ユーザーからメールアドレスを削除しました" + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "APIキーの作成に成功しました" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "APIキーのリセットに成功しました" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "APIキーの削除に成功しました" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 msgid "None" msgstr "なし" -#: rhodecode/controllers/admin/permissions.py:59 -#: rhodecode/controllers/admin/permissions.py:63 -#: rhodecode/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 msgid "Read" msgstr "読込" -#: rhodecode/controllers/admin/permissions.py:60 -#: rhodecode/controllers/admin/permissions.py:64 -#: rhodecode/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 msgid "Write" msgstr "書込" -#: rhodecode/controllers/admin/permissions.py:61 -#: rhodecode/controllers/admin/permissions.py:65 -#: rhodecode/controllers/admin/permissions.py:69 -#: rhodecode/templates/admin/defaults/defaults.html:9 -#: rhodecode/templates/admin/ldap/ldap.html:9 -#: rhodecode/templates/admin/permissions/permissions.html:9 -#: rhodecode/templates/admin/repos/repo_add.html:10 -#: rhodecode/templates/admin/repos/repo_add.html:14 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:13 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:9 -#: rhodecode/templates/admin/users/user_add.html:8 -#: rhodecode/templates/admin/users/user_edit.html:9 -#: rhodecode/templates/admin/users/user_edit.html:133 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/admin/users/users.html:85 -#: rhodecode/templates/admin/users_groups/users_group_add.html:8 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 -#: rhodecode/templates/admin/users_groups/users_groups.html:9 -#: rhodecode/templates/base/base.html:317 -#: rhodecode/templates/base/base.html:318 -#: rhodecode/templates/base/base.html:324 -#: rhodecode/templates/base/base.html:325 +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 msgid "Admin" msgstr "管理" -#: rhodecode/controllers/admin/permissions.py:72 -#: rhodecode/controllers/admin/permissions.py:83 -#: rhodecode/controllers/admin/permissions.py:86 -#: rhodecode/controllers/admin/permissions.py:89 -#: rhodecode/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 msgid "Disabled" msgstr "無効" -#: rhodecode/controllers/admin/permissions.py:74 +#: kallithea/controllers/admin/permissions.py:78 msgid "Allowed with manual account activation" -msgstr "手動でアカウントを有効にする" - -#: rhodecode/controllers/admin/permissions.py:76 +msgstr "手動でアカウントをアクティベートする" + +#: kallithea/controllers/admin/permissions.py:80 msgid "Allowed with automatic account activation" -msgstr "自動でアカウントを有効にする" - -#: rhodecode/controllers/admin/permissions.py:79 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1439 rhodecode/model/db.py:1444 +msgstr "自動でアカウントをアクティベートする" + +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 msgid "Manual activation of external account" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:80 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1440 rhodecode/model/db.py:1445 +msgstr "外部アカウントを手動でアクティベートする" + +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 msgid "Automatic activation of external account" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:84 -#: rhodecode/controllers/admin/permissions.py:87 -#: rhodecode/controllers/admin/permissions.py:90 -#: rhodecode/controllers/admin/permissions.py:93 +msgstr "外部アカウントを自動でアクティベートする" + +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 msgid "Enabled" msgstr "有効" -#: rhodecode/controllers/admin/permissions.py:138 -msgid "Default permissions updated successfully" -msgstr "デフォルトの権限を更新しました" - -#: rhodecode/controllers/admin/permissions.py:152 +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "全般の権限の更新に成功しました" + +#: kallithea/controllers/admin/permissions.py:139 msgid "Error occurred during update of permissions" msgstr "権限の更新中にエラーが発生しました" -#: rhodecode/controllers/admin/repos.py:128 -msgid "--REMOVE FORK--" -msgstr "--フォーク元を削除--" - -#: rhodecode/controllers/admin/repos.py:168 +#: kallithea/controllers/admin/repo_groups.py:186 +#, python-format +msgid "Created repository group %s" +msgstr "リポジトリグループ %s を作成しました" + +#: kallithea/controllers/admin/repo_groups.py:198 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "リポジトリグループ %s の作成中にエラーが発生しました" + +#: kallithea/controllers/admin/repo_groups.py:256 +#, python-format +msgid "Updated repository group %s" +msgstr "リポジトリグループ %s を更新しました" + +#: kallithea/controllers/admin/repo_groups.py:271 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "リポジトリグループ %s の更新中にエラーが発生しました" + +#: kallithea/controllers/admin/repo_groups.py:289 +#, python-format +msgid "This group contains %s repositores and cannot be deleted" +msgstr "このグループは %s 個のリポジトリを含んでいるため削除できません" + +#: kallithea/controllers/admin/repo_groups.py:296 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "このグループは %s 個のサブグループを含んでいるため削除できません" + +#: kallithea/controllers/admin/repo_groups.py:302 +#, python-format +msgid "Removed repository group %s" +msgstr "リポジトリグループ %s を削除しました" + +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "リポジトリグループ %s の削除中にエラーが発生しました" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "自分自身の管理者としての権限を取り消すことはできません" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "リポジトリグループ権限を更新しました" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "権限の取消中にエラーが発生しました" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "リポジトリ %s の作成中にエラーが発生しました" + +#: kallithea/controllers/admin/repos.py:237 #, python-format msgid "Created repository %s from %s" msgstr "リポジトリ %s を %s から作成しました" -#: rhodecode/controllers/admin/repos.py:174 +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "リポジトリ %s を %s としてフォークしました" + +#: kallithea/controllers/admin/repos.py:249 #, python-format msgid "Created repository %s" msgstr "リポジトリ %s を作成しました" -#: rhodecode/controllers/admin/repos.py:197 -#, python-format -msgid "Error creating repository %s" -msgstr "リポジトリ %s の作成中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos.py:270 +#: kallithea/controllers/admin/repos.py:289 #, python-format msgid "Repository %s updated successfully" msgstr "リポジトリ %s の更新に成功しました" -#: rhodecode/controllers/admin/repos.py:288 +#: kallithea/controllers/admin/repos.py:307 #, python-format msgid "Error occurred during update of repository %s" msgstr "リポジトリ %s の更新中にエラーが発生しました" -#: rhodecode/controllers/admin/repos.py:315 +#: kallithea/controllers/admin/repos.py:334 #, python-format msgid "Detached %s forks" msgstr "%s 個のフォークを切り離しました" -#: rhodecode/controllers/admin/repos.py:318 +#: kallithea/controllers/admin/repos.py:337 #, python-format msgid "Deleted %s forks" msgstr "%s 個のフォークを削除しました" -#: rhodecode/controllers/admin/repos.py:323 +#: kallithea/controllers/admin/repos.py:342 #, python-format msgid "Deleted repository %s" msgstr "リポジトリ %s を削除しました" -#: rhodecode/controllers/admin/repos.py:326 +#: kallithea/controllers/admin/repos.py:345 #, python-format msgid "Cannot delete %s it still contains attached forks" msgstr "フォークしたリポジトリが存在するため、 %s は削除できません" -#: rhodecode/controllers/admin/repos.py:331 +#: kallithea/controllers/admin/repos.py:350 #, python-format msgid "An error occurred during deletion of %s" -msgstr "リポジトリ %s の削除中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos.py:345 +msgstr "%s の削除中にエラーが発生しました" + +#: kallithea/controllers/admin/repos.py:402 msgid "Repository permissions updated" msgstr "リポジトリ権限を更新しました" -#: rhodecode/controllers/admin/repos.py:375 -#: rhodecode/controllers/admin/repos_groups.py:332 -#: rhodecode/controllers/admin/users_groups.py:312 -msgid "An error occurred during revoking of permission" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:392 -msgid "An error occurred during deletion of repository stats" -msgstr "リポジトリステートの削除中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos.py:409 -msgid "An error occurred during cache invalidation" -msgstr "キャッシュの無効化中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos.py:429 -#: rhodecode/controllers/admin/repos.py:456 +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "フィールドの作成中にエラーが発生しました" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "フィールドの削除中にエラーが発生しました" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "-- フォークではありません --" + +#: kallithea/controllers/admin/repos.py:522 +msgid "Updated repository visibility in public journal" +msgstr "公開ジャーナルでのリポジトリの可視性を更新しました" + +#: kallithea/controllers/admin/repos.py:526 +msgid "An error occurred during setting this repository in public journal" +msgstr "このリポジトリの公開ジャーナルの設定中にエラーが発生しました" + +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 +msgid "Token mismatch" +msgstr "トークンが一致しません" + +#: kallithea/controllers/admin/repos.py:546 +msgid "Nothing" +msgstr "ありません" + +#: kallithea/controllers/admin/repos.py:548 +#, python-format +msgid "Marked repo %s as fork of %s" +msgstr "%s リポジトリを %s のフォークとする" + +#: kallithea/controllers/admin/repos.py:555 +msgid "An error occurred during this operation" +msgstr "操作中にエラーが発生しました" + +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "リポジトリをロックしました" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "リポジトリのロックを解除しました" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 msgid "An error occurred during unlocking" msgstr "アンロック中にエラーが発生しました" -#: rhodecode/controllers/admin/repos.py:447 +#: kallithea/controllers/admin/repos.py:595 msgid "Unlocked" msgstr "アンロック" -#: rhodecode/controllers/admin/repos.py:450 +#: kallithea/controllers/admin/repos.py:598 msgid "Locked" msgstr "ロック" -#: rhodecode/controllers/admin/repos.py:452 +#: kallithea/controllers/admin/repos.py:600 #, python-format msgid "Repository has been %s" msgstr "リポジトリは %s されています" -#: rhodecode/controllers/admin/repos.py:476 -msgid "Updated repository visibility in public journal" -msgstr "公開ジャーナルでのリポジトリの可視性を更新しました" - -#: rhodecode/controllers/admin/repos.py:480 -msgid "An error occurred during setting this repository in public journal" -msgstr "このリポジトリの公開ジャーナルの設定中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos.py:485 rhodecode/model/validators.py:302 -msgid "Token mismatch" -msgstr "トークンが合いません" - -#: rhodecode/controllers/admin/repos.py:498 +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "キャッシュの無効化に成功しました" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "キャッシュの無効化中にエラーが発生しました" + +#: kallithea/controllers/admin/repos.py:637 msgid "Pulled from remote location" msgstr "リモートから取得" -#: rhodecode/controllers/admin/repos.py:501 +#: kallithea/controllers/admin/repos.py:640 msgid "An error occurred during pull from remote location" msgstr "リモートから取得中にエラーが発生しました" -#: rhodecode/controllers/admin/repos.py:517 -msgid "Nothing" -msgstr "ありません" - -#: rhodecode/controllers/admin/repos.py:519 -#, python-format -msgid "Marked repo %s as fork of %s" -msgstr "%s リポジトリを %s のフォークとして印をつける" - -#: rhodecode/controllers/admin/repos.py:523 -msgid "An error occurred during this operation" -msgstr "操作中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos.py:562 -msgid "An error occurred during creation of field" -msgstr "フィールドの作成中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos.py:576 -msgid "An error occurred during removal of field" -msgstr "フィールドの削除中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos_groups.py:147 -#, python-format -msgid "Created repository group %s" -msgstr "リポジトリグループ %s を作成しました" - -#: rhodecode/controllers/admin/repos_groups.py:159 -#, python-format -msgid "Error occurred during creation of repository group %s" -msgstr "リポジトリグループ %s の作成中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos_groups.py:217 -#, python-format -msgid "Updated repository group %s" -msgstr "リポジトリグループ %s を更新しました" - -#: rhodecode/controllers/admin/repos_groups.py:232 -#, python-format -msgid "Error occurred during update of repository group %s" -msgstr "リポジトリグループ %s の更新中にエラーが発生しました" - -#: rhodecode/controllers/admin/repos_groups.py:250 -#, python-format -msgid "This group contains %s repositores and cannot be deleted" -msgstr "このグループは %s リポジトリを含んでいるため削除出来ません" - -#: rhodecode/controllers/admin/repos_groups.py:257 -#, python-format -msgid "This group contains %s subgroups and cannot be deleted" -msgstr "このグループは %s サブグループを含んでいるため削除出来ません" - -#: rhodecode/controllers/admin/repos_groups.py:263 -#, python-format -msgid "Removed repository group %s" -msgstr "リポジトリグループ %s を削除しました" - -#: rhodecode/controllers/admin/repos_groups.py:268 -#, python-format -msgid "Error occurred during deletion of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:279 -#: rhodecode/controllers/admin/repos_groups.py:314 -#: rhodecode/controllers/admin/users_groups.py:300 -msgid "Cannot revoke permission for yourself as admin" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:294 -msgid "Repository Group permissions updated" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:123 +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "リポジトリステートの削除中にエラーが発生しました" + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "VCS設定を更新しました" + +#: kallithea/controllers/admin/settings.py:176 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "\"hgsubversion\"ライブラリが見つからないため、hgsubversionサポートを有効に出来ません。" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "アプリケーション設定の更新中にエラーが発生しました" + +#: kallithea/controllers/admin/settings.py:215 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" msgstr "リポジトリの再スキャンに成功しました。 追加: %s 削除: %s" -#: rhodecode/controllers/admin/settings.py:132 -msgid "Whoosh reindex task scheduled" -msgstr "Whooshの再インデックスタスクを予定に入れました" - -#: rhodecode/controllers/admin/settings.py:163 +#: kallithea/controllers/admin/settings.py:270 msgid "Updated application settings" msgstr "アプリケーション設定を更新しました" -#: rhodecode/controllers/admin/settings.py:167 -#: rhodecode/controllers/admin/settings.py:304 -msgid "Error occurred during updating application settings" -msgstr "アプリケーション設定の更新中にエラーが発生しました" - -#: rhodecode/controllers/admin/settings.py:219 +#: kallithea/controllers/admin/settings.py:327 msgid "Updated visualisation settings" msgstr "表示設定を更新しました" -#: rhodecode/controllers/admin/settings.py:224 +#: kallithea/controllers/admin/settings.py:332 msgid "Error occurred during updating visualisation settings" msgstr "表示設定の更新中にエラーが発生しました" -#: rhodecode/controllers/admin/settings.py:300 -msgid "Updated VCS settings" -msgstr "VCS設定を更新しました" - -#: rhodecode/controllers/admin/settings.py:314 +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "メールアドレスを入力してください" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "メール送信タスクを作成しました" + +#: kallithea/controllers/admin/settings.py:400 msgid "Added new hook" msgstr "新しいフックを追加しました" -#: rhodecode/controllers/admin/settings.py:326 +#: kallithea/controllers/admin/settings.py:414 msgid "Updated hooks" msgstr "フックを更新しました" -#: rhodecode/controllers/admin/settings.py:330 +#: kallithea/controllers/admin/settings.py:418 msgid "Error occurred during hook creation" msgstr "フックの作成中にエラーが発生しました" -#: rhodecode/controllers/admin/settings.py:349 -msgid "Email task created" -msgstr "メールのタスクを作成しました" - -#: rhodecode/controllers/admin/settings.py:413 -msgid "You can't edit this user since it's crucial for entire application" -msgstr "このユーザーを編集出来ません。このユーザーはアプリケーションにとって必要不可欠です。" - -#: rhodecode/controllers/admin/settings.py:455 -msgid "Your account was updated successfully" -msgstr "アカウントを更新しました" - -#: rhodecode/controllers/admin/settings.py:470 -#: rhodecode/controllers/admin/users.py:198 -#, python-format -msgid "Error occurred during update of user %s" -msgstr "ユーザー %s の更新中にエラーが発生しました" - -#: rhodecode/controllers/admin/users.py:130 +#: kallithea/controllers/admin/settings.py:444 +msgid "Whoosh reindex task scheduled" +msgstr "Whooshの再インデックスタスクを予定に入れました" + +#: kallithea/controllers/admin/user_groups.py:150 +#, python-format +msgid "Created user group %s" +msgstr "ユーザーグループ %s を作成しました" + +#: kallithea/controllers/admin/user_groups.py:161 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "ユーザーグループ %s の作成中にエラーが発生しました" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Updated user group %s" +msgstr "ユーザーグループ %s を更新しました" + +#: kallithea/controllers/admin/user_groups.py:221 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "ユーザーグループ %s の更新中にエラーが発生しました" + +#: kallithea/controllers/admin/user_groups.py:239 +msgid "Successfully deleted user group" +msgstr "ユーザーグループの削除に成功しました" + +#: kallithea/controllers/admin/user_groups.py:244 +msgid "An error occurred during deletion of user group" +msgstr "ユーザーグループの削除中にエラーが発生しました" + +#: kallithea/controllers/admin/user_groups.py:311 +msgid "Target group cannot be the same" +msgstr "対象に同じ物を選ぶことはできません" + +#: kallithea/controllers/admin/user_groups.py:317 +msgid "User Group permissions updated" +msgstr "ユーザーグループ権限を更新しました" + +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "権限を更新しました" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "権限の保存時にエラーが発生しました" + +#: kallithea/controllers/admin/users.py:135 #, python-format msgid "Created user %s" msgstr "ユーザー %s を作成しました" -#: rhodecode/controllers/admin/users.py:142 +#: kallithea/controllers/admin/users.py:149 #, python-format msgid "Error occurred during creation of user %s" msgstr "ユーザー %s の作成中にエラーが発生しました" -#: rhodecode/controllers/admin/users.py:176 +#: kallithea/controllers/admin/users.py:188 msgid "User updated successfully" msgstr "ユーザーの更新に成功しました" -#: rhodecode/controllers/admin/users.py:214 +#: kallithea/controllers/admin/users.py:223 msgid "Successfully deleted user" msgstr "ユーザーの削除に成功しました" -#: rhodecode/controllers/admin/users.py:219 +#: kallithea/controllers/admin/users.py:228 msgid "An error occurred during deletion of user" msgstr "ユーザーの削除中にエラーが発生しました" -#: rhodecode/controllers/admin/users.py:234 +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 msgid "You can't edit this user" msgstr "このユーザーは編集できません" -#: rhodecode/controllers/admin/users.py:293 -#: rhodecode/controllers/admin/users_groups.py:372 -msgid "Updated permissions" -msgstr "" - -#: rhodecode/controllers/admin/users.py:297 -#: rhodecode/controllers/admin/users_groups.py:376 -msgid "An error occurred during permissions saving" -msgstr "権限の保存時にエラーが発生しました" - -#: rhodecode/controllers/admin/users.py:311 -#, python-format -msgid "Added email %s to user" -msgstr "ユーザーにメール %s を追加しました" - -#: rhodecode/controllers/admin/users.py:317 -msgid "An error occurred during email saving" -msgstr "メールの保存時にエラーが発生しました" - -#: rhodecode/controllers/admin/users.py:327 -msgid "Removed email from user" -msgstr "ユーザーからメールを削除しました" - -#: rhodecode/controllers/admin/users.py:340 -#, python-format -msgid "Added ip %s to user" -msgstr "ユーザーにIPアドレス %s を追加しました" - -#: rhodecode/controllers/admin/users.py:346 +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "ユーザーホワイトリストにIP %s を追加しました" + +#: kallithea/controllers/admin/users.py:489 msgid "An error occurred during ip saving" msgstr "IPアドレスの保存中にエラーが発生しました" -#: rhodecode/controllers/admin/users.py:358 -msgid "Removed ip from user" -msgstr "ユーザーからIPアドレスを削除しました" - -#: rhodecode/controllers/admin/users_groups.py:162 -#, python-format -msgid "Created user group %s" -msgstr "ユーザーグループ %s を作成しました" - -#: rhodecode/controllers/admin/users_groups.py:173 -#, python-format -msgid "Error occurred during creation of user group %s" -msgstr "ユーザーグループ %s の作成中にエラーが発生しました" - -#: rhodecode/controllers/admin/users_groups.py:210 -#, python-format -msgid "Updated user group %s" -msgstr "ユーザーグループ %s を更新しました" - -#: rhodecode/controllers/admin/users_groups.py:232 -#, python-format -msgid "Error occurred during update of user group %s" -msgstr "ユーザーグループ %s の更新中にエラーが発生しました" - -#: rhodecode/controllers/admin/users_groups.py:250 -msgid "Successfully deleted user group" -msgstr "ユーザーグループの削除に成功しました" - -#: rhodecode/controllers/admin/users_groups.py:255 -msgid "An error occurred during deletion of user group" -msgstr "ユーザーグループの削除中にエラーが発生しました" - -#: rhodecode/controllers/admin/users_groups.py:274 -msgid "Target group cannot be the same" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:280 -msgid "User Group permissions updated" -msgstr "" - -#: rhodecode/lib/auth.py:544 +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "ユーザーホワイトリストからIPアドレスを削除しました" + +#: kallithea/lib/auth.py:748 #, python-format msgid "IP %s not allowed" msgstr "IPアドレス %s は許可されません" -#: rhodecode/lib/auth.py:593 +#: kallithea/lib/auth.py:809 msgid "You need to be a registered user to perform this action" -msgstr "このアクションを実行するためには登録ユーザーである必要があります" - -#: rhodecode/lib/auth.py:634 +msgstr "このアクションを実行するためには登録済みのユーザーである必要があります" + +#: kallithea/lib/auth.py:846 msgid "You need to be a signed in to view this page" msgstr "このページを閲覧するためにはサインインが必要です" -#: rhodecode/lib/diffs.py:66 +#: kallithea/lib/diffs.py:66 msgid "Binary file" msgstr "バイナリファイル" -#: rhodecode/lib/diffs.py:82 -msgid "" -"Changeset was too big and was cut off, use diff menu to display this diff" +#: kallithea/lib/diffs.py:82 +msgid "Changeset was too big and was cut off, use diff menu to display this diff" msgstr "チェンジセットが大きすぎるため省略しました。差分を表示する場合は差分メニューを使用してください" -#: rhodecode/lib/diffs.py:92 +#: kallithea/lib/diffs.py:92 msgid "No changes detected" msgstr "検出された変更はありません" -#: rhodecode/lib/helpers.py:539 -msgid "True" -msgstr "True" - -#: rhodecode/lib/helpers.py:542 -msgid "False" -msgstr "False" - -#: rhodecode/lib/helpers.py:580 +#: kallithea/lib/helpers.py:598 #, python-format msgid "Deleted branch: %s" msgstr "削除されたブランチ: %s" -#: rhodecode/lib/helpers.py:583 +#: kallithea/lib/helpers.py:601 #, python-format msgid "Created tag: %s" msgstr "作成したタグ: %s" -#: rhodecode/lib/helpers.py:596 +#: kallithea/lib/helpers.py:614 msgid "Changeset not found" msgstr "リビジョンが見つかりません" -#: rhodecode/lib/helpers.py:646 +#: kallithea/lib/helpers.py:664 #, python-format msgid "Show all combined changesets %s->%s" msgstr "%s から %s までのすべてのチェンジセットを表示" -#: rhodecode/lib/helpers.py:652 +#: kallithea/lib/helpers.py:670 msgid "compare view" -msgstr "比較の表示" - -#: rhodecode/lib/helpers.py:672 +msgstr "比較ビュー" + +#: kallithea/lib/helpers.py:690 msgid "and" msgstr "と" -#: rhodecode/lib/helpers.py:673 +#: kallithea/lib/helpers.py:691 #, python-format msgid "%s more" msgstr "%s 以上" -#: rhodecode/lib/helpers.py:674 -#: rhodecode/templates/changelog/changelog.html:53 +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 msgid "revisions" msgstr "リビジョン" -#: rhodecode/lib/helpers.py:698 +#: kallithea/lib/helpers.py:716 #, python-format msgid "fork name %s" msgstr "フォーク名 %s" -#: rhodecode/lib/helpers.py:715 -#: rhodecode/templates/pullrequests/pullrequest_show.html:8 +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 #, python-format msgid "Pull request #%s" msgstr "プルリクエスト #%s" -#: rhodecode/lib/helpers.py:725 +#: kallithea/lib/helpers.py:743 msgid "[deleted] repository" msgstr "リポジトリを[削除]" -#: rhodecode/lib/helpers.py:727 rhodecode/lib/helpers.py:739 +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 msgid "[created] repository" msgstr "リポジトリを[作成]" -#: rhodecode/lib/helpers.py:729 +#: kallithea/lib/helpers.py:747 msgid "[created] repository as fork" msgstr "フォークしてリポジトリを[作成]" -#: rhodecode/lib/helpers.py:731 rhodecode/lib/helpers.py:741 +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 msgid "[forked] repository" msgstr "リポジトリを[フォーク]" -#: rhodecode/lib/helpers.py:733 rhodecode/lib/helpers.py:743 +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 msgid "[updated] repository" msgstr "リポジトリを[更新]" -#: rhodecode/lib/helpers.py:735 +#: kallithea/lib/helpers.py:753 msgid "[downloaded] archive from repository" -msgstr "" - -#: rhodecode/lib/helpers.py:737 +msgstr "リポジトリからアーカイブを[ダウンロード]" + +#: kallithea/lib/helpers.py:755 msgid "[delete] repository" msgstr "リポジトリを[削除]" -#: rhodecode/lib/helpers.py:745 +#: kallithea/lib/helpers.py:763 msgid "[created] user" msgstr "ユーザーを[作成]" -#: rhodecode/lib/helpers.py:747 +#: kallithea/lib/helpers.py:765 msgid "[updated] user" msgstr "ユーザーを[更新]" -#: rhodecode/lib/helpers.py:749 +#: kallithea/lib/helpers.py:767 msgid "[created] user group" msgstr "ユーザーグループを[作成]" -#: rhodecode/lib/helpers.py:751 +#: kallithea/lib/helpers.py:769 msgid "[updated] user group" msgstr "ユーザーグループを[更新]" -#: rhodecode/lib/helpers.py:753 +#: kallithea/lib/helpers.py:771 msgid "[commented] on revision in repository" msgstr "リポジトリのリビジョンに[コメント]" -#: rhodecode/lib/helpers.py:755 +#: kallithea/lib/helpers.py:773 msgid "[commented] on pull request for" msgstr "プルリクエストに[コメント]" -#: rhodecode/lib/helpers.py:757 +#: kallithea/lib/helpers.py:775 msgid "[closed] pull request for" msgstr "プルリクエストを[クローズ]" -#: rhodecode/lib/helpers.py:759 +#: kallithea/lib/helpers.py:777 msgid "[pushed] into" msgstr "[プッシュ]" -#: rhodecode/lib/helpers.py:761 -msgid "[committed via RhodeCode] into repository" -msgstr "リポジトリに[RhodeCode経由でコミット]" - -#: rhodecode/lib/helpers.py:763 +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "リポジトリに[Kallithea経由でコミット]" + +#: kallithea/lib/helpers.py:781 msgid "[pulled from remote] into repository" msgstr "リポジトリに[リモートからプル]" -#: rhodecode/lib/helpers.py:765 +#: kallithea/lib/helpers.py:783 msgid "[pulled] from" msgstr "[プル]" -#: rhodecode/lib/helpers.py:767 +#: kallithea/lib/helpers.py:785 msgid "[started following] repository" msgstr "リポジトリの[フォローを開始]" -#: rhodecode/lib/helpers.py:769 +#: kallithea/lib/helpers.py:787 msgid "[stopped following] repository" msgstr "リポジトリの[フォローを停止]" -#: rhodecode/lib/helpers.py:1088 +#: kallithea/lib/helpers.py:1101 #, python-format msgid " and %s more" msgstr " と %s 以上" -#: rhodecode/lib/helpers.py:1092 +#: kallithea/lib/helpers.py:1105 msgid "No Files" msgstr "ファイルなし" -#: rhodecode/lib/helpers.py:1158 +#: kallithea/lib/helpers.py:1171 msgid "new file" -msgstr "" - -#: rhodecode/lib/helpers.py:1161 +msgstr "新しいファイル" + +#: kallithea/lib/helpers.py:1174 msgid "mod" -msgstr "" - -#: rhodecode/lib/helpers.py:1164 +msgstr "変更" + +#: kallithea/lib/helpers.py:1177 msgid "del" -msgstr "" - -#: rhodecode/lib/helpers.py:1167 +msgstr "削除" + +#: kallithea/lib/helpers.py:1180 msgid "rename" -msgstr "" - -#: rhodecode/lib/helpers.py:1172 +msgstr "リネーム" + +#: kallithea/lib/helpers.py:1185 msgid "chmod" -msgstr "" - -#: rhodecode/lib/helpers.py:1404 +msgstr "chmod" + +#: kallithea/lib/helpers.py:1417 #, python-format msgid "" -"%s repository is not mapped to db perhaps it was created or renamed from the" -" filesystem please run the application again in order to rescan repositories" -msgstr "%s リポジトリはDB内に見つかりませんでした。おそらくファイルシステム上で作られたか名前が変更されたためです。リポジトリをもう一度チェックするためにアプリケーションを立ち上げ直してください。" - -#: rhodecode/lib/unionrepo.py:193 -msgid "cannot create new union repository" -msgstr "新しいユニオンリポジトリは作成できません" - -#: rhodecode/lib/utils2.py:410 +"%s repository is not mapped to db perhaps it was created or renamed from " +"the filesystem please run the application again in order to rescan " +"repositories" +msgstr "" +"%s " +"リポジトリはDB内に見つかりませんでした。おそらくファイルシステム上で作られたか名前が変更されたためです。リポジトリをもう一度チェックするためにアプリケーションを立ち上げ直してください。" + +#: kallithea/lib/utils2.py:415 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d 年" -#: rhodecode/lib/utils2.py:411 +#: kallithea/lib/utils2.py:416 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d ヶ月" -#: rhodecode/lib/utils2.py:412 +#: kallithea/lib/utils2.py:417 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d 日" -#: rhodecode/lib/utils2.py:413 +#: kallithea/lib/utils2.py:418 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d 時間" -#: rhodecode/lib/utils2.py:414 +#: kallithea/lib/utils2.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d 分" -#: rhodecode/lib/utils2.py:415 +#: kallithea/lib/utils2.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d 秒" -#: rhodecode/lib/utils2.py:431 +#: kallithea/lib/utils2.py:436 #, python-format msgid "in %s" -msgstr "" - -#: rhodecode/lib/utils2.py:433 +msgstr "%s 以内" + +#: kallithea/lib/utils2.py:438 #, python-format msgid "%s ago" msgstr "%s 前" -#: rhodecode/lib/utils2.py:435 +#: kallithea/lib/utils2.py:440 #, python-format msgid "in %s and %s" -msgstr "" - -#: rhodecode/lib/utils2.py:438 +msgstr "%s と %s の間" + +#: kallithea/lib/utils2.py:443 #, python-format msgid "%s and %s ago" msgstr "%s と %s 前" -#: rhodecode/lib/utils2.py:441 +#: kallithea/lib/utils2.py:446 msgid "just now" -msgstr "ちょうどいま" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1163 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1303 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1388 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1408 rhodecode/model/db.py:1413 +msgstr "たったいま" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 msgid "Repository no access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1164 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1184 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1304 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1389 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1409 rhodecode/model/db.py:1414 +msgstr "リポジトリへのアクセス権限無し" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 msgid "Repository read access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1165 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1185 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1305 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1390 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1410 rhodecode/model/db.py:1415 +msgstr "リポジトリに読込権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 msgid "Repository write access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1166 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1186 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1306 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1391 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1411 rhodecode/model/db.py:1416 +msgstr "リポジトリに書込権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 msgid "Repository admin access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1168 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1308 +msgstr "リポジトリに管理権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 msgid "Repositories Group no access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1169 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1309 +msgstr "リポジトリグループへのアクセス権限なし" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 msgid "Repositories Group read access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1170 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1310 +msgstr "リポジトリグループに読込権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 msgid "Repositories Group write access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1171 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1311 +msgstr "リポジトリグループに書込権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 msgid "Repositories Group admin access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1173 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1193 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1313 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1398 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1406 rhodecode/model/db.py:1411 -msgid "RhodeCode Administrator" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1174 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1194 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1314 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1399 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1429 rhodecode/model/db.py:1434 +msgstr "リポジトリグループに管理権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" +msgstr "Kallithea 管理者" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 msgid "Repository creation disabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1175 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1195 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1315 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1400 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1430 rhodecode/model/db.py:1435 +msgstr "リポジトリの作成を有効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 msgid "Repository creation enabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1176 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1196 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1316 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1401 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1432 rhodecode/model/db.py:1437 +msgstr "リポジトリの作成を有効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 msgid "Repository forking disabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1177 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1197 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1317 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1402 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1433 rhodecode/model/db.py:1438 +msgstr "リポジトリのフォークを無効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 msgid "Repository forking enabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1178 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1318 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1403 +msgstr "リポジトリのフォークを有効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 msgid "Register disabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1319 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1404 -msgid "Register new user with RhodeCode with manual activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1202 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1407 -msgid "Register new user with RhodeCode with auto activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1623 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1643 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1763 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1838 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1934 rhodecode/model/db.py:1939 +msgstr "新規登録を無効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" +msgstr "Kallitheaに登録した新しいユーザーを手動でアクティベートする" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" +msgstr "Kallitheaに登録した新しいユーザーを自動でアクティベートする" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 msgid "Not Reviewed" msgstr "未レビュー" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1624 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1644 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1764 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1839 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1935 rhodecode/model/db.py:1940 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 msgid "Approved" msgstr "承認" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1625 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1645 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1765 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1840 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1936 rhodecode/model/db.py:1941 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 msgid "Rejected" msgstr "却下" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1626 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1646 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1766 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1841 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1937 rhodecode/model/db.py:1942 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 msgid "Under Review" msgstr "レビュー中" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1252 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1270 rhodecode/model/db.py:1275 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 msgid "top level" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1393 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1413 rhodecode/model/db.py:1418 +msgstr "top level" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 msgid "Repository group no access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1394 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1414 rhodecode/model/db.py:1419 +msgstr "リポジトリグループへのアクセス権限なし" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 msgid "Repository group read access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1395 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1415 rhodecode/model/db.py:1420 +msgstr "リポジトリグループに読込権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 msgid "Repository group write access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1396 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1416 rhodecode/model/db.py:1421 +msgstr "リポジトリグループに書込権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 msgid "Repository group admin access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1418 rhodecode/model/db.py:1423 +msgstr "リポジトリグループに管理権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 msgid "User group no access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1419 rhodecode/model/db.py:1424 +msgstr "ユーザーグループへのアクセス権限なし" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 msgid "User group read access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1420 rhodecode/model/db.py:1425 +msgstr "ユーザーグループに読込権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 msgid "User group write access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1421 rhodecode/model/db.py:1426 +msgstr "ユーザーグループに書込権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 msgid "User group admin access" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1423 rhodecode/model/db.py:1428 +msgstr "ユーザーグループに管理権限でアクセス" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 msgid "Repository Group creation disabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1424 rhodecode/model/db.py:1429 +msgstr "リポジトリグループの作成を無効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 msgid "Repository Group creation enabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1426 rhodecode/model/db.py:1431 +msgstr "リポジトリグループの作成を有効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 msgid "User Group creation disabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1427 rhodecode/model/db.py:1432 +msgstr "ユーザーグループの作成を無効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 msgid "User Group creation enabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1435 rhodecode/model/db.py:1440 +msgstr "ユーザーグループの作成を有効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 msgid "Registration disabled" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1436 rhodecode/model/db.py:1441 +msgstr "新規登録を無効にする" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 msgid "User Registration with manual account activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1437 rhodecode/model/db.py:1442 +msgstr "ユーザーの新規登録時に手動でアカウントをアクティベートする" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 msgid "User Registration with automatic account activation" -msgstr "" - -#: rhodecode/model/comment.py:75 +msgstr "ユーザーの新規登録時に自動でアカウントをアクティベートする" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "リポジトリグループの書き込みパーミッションを使ったリポジトリ作成が有効です" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "リポジトリグループの書き込みパーミッションを使ったリポジトリ作成は無効です" + +#: kallithea/model/comment.py:77 #, python-format msgid "on line %s" -msgstr "" - -#: rhodecode/model/comment.py:220 +msgstr "%s 行目" + +#: kallithea/model/comment.py:222 msgid "[Mention]" msgstr "[Mention]" -#: rhodecode/model/forms.py:43 +#: kallithea/model/forms.py:57 msgid "Please enter a login" msgstr "ログイン名を入力してください" -#: rhodecode/model/forms.py:44 +#: kallithea/model/forms.py:58 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "%(min)i 文字以上必要です" -#: rhodecode/model/forms.py:52 +#: kallithea/model/forms.py:66 msgid "Please enter a password" msgstr "パスワードを入力してください" -#: rhodecode/model/forms.py:53 +#: kallithea/model/forms.py:67 #, python-format msgid "Enter %(min)i characters or more" msgstr "%(min)i 文字以上必要です" -#: rhodecode/model/notification.py:228 +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "数字だけの名前は使えません" + +#: kallithea/model/notification.py:231 #, python-format msgid "%(user)s commented on changeset at %(when)s" -msgstr "%(user)s がコミットにコメント %(when)s" - -#: rhodecode/model/notification.py:229 +msgstr "%(user)s がチェンジセットにコメント %(when)s" + +#: kallithea/model/notification.py:232 #, python-format msgid "%(user)s sent message at %(when)s" msgstr "%(user)s がメッセージを送信 %(when)s" -#: rhodecode/model/notification.py:230 +#: kallithea/model/notification.py:233 #, python-format msgid "%(user)s mentioned you at %(when)s" -msgstr "%(user)s があなたにメンション %(when)s" - -#: rhodecode/model/notification.py:231 -#, python-format -msgid "%(user)s registered in RhodeCode at %(when)s" -msgstr "%(user)s がRhodeCodeに登録 %(when)s" - -#: rhodecode/model/notification.py:232 +msgstr "%(user)s がにあなたにメンション %(when)s" + +#: kallithea/model/notification.py:234 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "%(user)s がKallitheaに登録 %(when)s" + +#: kallithea/model/notification.py:235 #, python-format msgid "%(user)s opened new pull request at %(when)s" msgstr "%(user)s が新しいプルリクエストを作成 %(when)s" -#: rhodecode/model/notification.py:233 +#: kallithea/model/notification.py:236 #, python-format msgid "%(user)s commented on pull request at %(when)s" msgstr "%(user)s がプルリクエストにコメント %(when)s" -#: rhodecode/model/pull_request.py:98 +#: kallithea/model/pull_request.py:107 #, python-format msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" -msgstr "%(user)s がプリリクエスト #%(pr_id)s のレビューを求めています %(pr_title)s" - -#: rhodecode/model/scm.py:674 +msgstr "%(user)s がプリリクエスト #%(pr_id)s: %(pr_title)s のレビューを求めています" + +#: kallithea/model/scm.py:810 msgid "latest tip" msgstr "最新のtip" -#: rhodecode/model/user.py:232 +#: kallithea/model/user.py:198 msgid "New user registration" msgstr "新規ユーザー登録" -#: rhodecode/model/user.py:257 rhodecode/model/user.py:281 +#: kallithea/model/user.py:222 kallithea/model/user.py:247 msgid "You can't Edit this user since it's crucial for entire application" -msgstr "アプリケーション全体にとって重要なユーザなため、編集出来ません" - -#: rhodecode/model/user.py:303 +msgstr "このユーザーを編集できません。このユーザーはアプリケーションにとって必要不可欠です。" + +#: kallithea/model/user.py:270 msgid "You can't remove this user since it's crucial for entire application" -msgstr "アプリケーション全体にとって重要なユーザなため、削除できません" - -#: rhodecode/model/user.py:309 +msgstr "このユーザーを削除できません。このユーザーはアプリケーションにとって必要不可欠です。" + +#: kallithea/model/user.py:276 #, python-format msgid "" -"user \"%s\" still owns %s repositories and cannot be removed. Switch owners " -"or remove those repositories. %s" -msgstr "" - -#: rhodecode/model/user.py:334 +"user \"%s\" still owns %s repositories and cannot be removed. Switch " +"owners or remove those repositories. %s" +msgstr "ユーザー \"%s\" はまだ %s 個のリポジトリの所有者のため削除することはできません。リポジトリの所有者を変更するか削除してください。 %s" + +#: kallithea/model/user.py:304 msgid "Password reset link" msgstr "パスワードリセットのリンク" -#: rhodecode/model/user.py:366 +#: kallithea/model/user.py:333 msgid "Your new password" msgstr "新しいパスワード" -#: rhodecode/model/user.py:367 -#, python-format -msgid "Your new RhodeCode password:%s" -msgstr "新しいRhodeCodeパスワード:%s" - -#: rhodecode/model/validators.py:38 rhodecode/model/validators.py:39 +#: kallithea/model/user.py:334 +#, python-format +msgid "Your new Kallithea password:%s" +msgstr "新しいKallitheaパスワード:%s" + +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 msgid "Value cannot be an empty list" -msgstr "空のリストには出来ません" - -#: rhodecode/model/validators.py:85 +msgstr "空のリストにはできません" + +#: kallithea/model/validators.py:120 #, python-format msgid "Username \"%(username)s\" already exists" msgstr "ユーザー名 \"%(username)s\" はすでに使われています" -#: rhodecode/model/validators.py:87 +#: kallithea/model/validators.py:122 #, python-format msgid "Username \"%(username)s\" is forbidden" msgstr "ユーザー名 \"%(username)s\" は許可されていません" -#: rhodecode/model/validators.py:89 +#: kallithea/model/validators.py:124 msgid "" -"Username may only contain alphanumeric characters underscores, periods or " -"dashes and must begin with alphanumeric character or underscore" -msgstr "" - -#: rhodecode/model/validators.py:117 +"Username may only contain alphanumeric characters underscores, periods or" +" dashes and must begin with alphanumeric character or underscore" +msgstr "ユーザー名はアルファベット、アンダースコア(_)、ピリオド(.)、ダッシュ(-)しか使えません。また、アルファベットまたはアンダースコア(_)から始まる必要があります" + +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "入力が正しくありません" + +#: kallithea/model/validators.py:158 #, python-format msgid "Username %(username)s is not valid" msgstr "ユーザー名 %(username)s は不正です" -#: rhodecode/model/validators.py:136 +#: kallithea/model/validators.py:177 msgid "Invalid user group name" msgstr "不正なユーザーグループ名です" -#: rhodecode/model/validators.py:137 +#: kallithea/model/validators.py:178 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "ユーザーグループ \"%(usergroup)s\" はすでに存在します" -#: rhodecode/model/validators.py:139 +#: kallithea/model/validators.py:180 msgid "" "user group name may only contain alphanumeric characters underscores, " "periods or dashes and must begin with alphanumeric character" -msgstr "ユーザーグループ名はアルファベット、アンダースコア(_)、ピリオド(.)、ダッシュ(-)しか使えません。また、アルファベットから始まる必要があります " - -#: rhodecode/model/validators.py:177 +msgstr "" +"ユーザーグループ名はアルファベット、アンダースコア(_)、ピリオド(.)、ダッシュ(-)しか使えません。また、アルファベットから始まる必要があります" +" " + +#: kallithea/model/validators.py:218 msgid "Cannot assign this group as parent" msgstr "このグループは親にできません" -#: rhodecode/model/validators.py:178 +#: kallithea/model/validators.py:219 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "グループ \"%(group_name)s\" はすでに存在します" -#: rhodecode/model/validators.py:180 +#: kallithea/model/validators.py:221 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "グループ名 \"%(group_name)s\" を持つリポジトリはすでに存在します" -#: rhodecode/model/validators.py:238 +#: kallithea/model/validators.py:279 msgid "Invalid characters (non-ascii) in password" msgstr "パスワードに利用出来ない文字列(non-ascii)です" -#: rhodecode/model/validators.py:253 +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 msgid "Passwords do not match" msgstr "パスワードが一致しません" -#: rhodecode/model/validators.py:270 +#: kallithea/model/validators.py:327 msgid "invalid password" msgstr "不正なパスワードです" -#: rhodecode/model/validators.py:271 +#: kallithea/model/validators.py:328 msgid "invalid user name" msgstr "不正なユーザー名です" -#: rhodecode/model/validators.py:272 +#: kallithea/model/validators.py:329 msgid "Your account is disabled" msgstr "アカウントは無効です" -#: rhodecode/model/validators.py:316 +#: kallithea/model/validators.py:373 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "リポジトリ名 %(repo)s は許可されていません" -#: rhodecode/model/validators.py:318 +#: kallithea/model/validators.py:375 #, python-format msgid "Repository named %(repo)s already exists" msgstr "リポジトリ %(repo)s はすでに存在します" -#: rhodecode/model/validators.py:319 +#: kallithea/model/validators.py:376 #, python-format msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" msgstr "リポジトリ \"%(repo)s\" は グループ \"%(group)s\" にすでに存在します" -#: rhodecode/model/validators.py:321 +#: kallithea/model/validators.py:378 #, python-format msgid "Repository group with name \"%(repo)s\" already exists" msgstr "リポジトリグループ名 \"%(repo)s\" はすでに存在します" -#: rhodecode/model/validators.py:438 +#: kallithea/model/validators.py:493 msgid "invalid clone url" msgstr "無効なクローンURIです" -#: rhodecode/model/validators.py:439 +#: kallithea/model/validators.py:494 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" msgstr "無効なクローンURIです。有効な http(s)/svn+http(s) のURIを指定してください" -#: rhodecode/model/validators.py:464 +#: kallithea/model/validators.py:519 msgid "Fork have to be the same type as parent" -msgstr "フォークは親と同じタイプの必要があります" - -#: rhodecode/model/validators.py:479 +msgstr "フォークは親と同じ種別の必要があります" + +#: kallithea/model/validators.py:534 msgid "You don't have permissions to create repository in this group" -msgstr "このグループでリポジトリを作成する権限がありません" - -#: rhodecode/model/validators.py:481 +msgstr "このグループにリポジトリを作成する権限がありません" + +#: kallithea/model/validators.py:536 msgid "no permission to create repository in root location" msgstr "ルートにリポジトリを作成する権限がありません" -#: rhodecode/model/validators.py:518 +#: kallithea/model/validators.py:585 msgid "You don't have permissions to create a group in this location" msgstr "この場所にグループを作成する権限がありません" -#: rhodecode/model/validators.py:559 +#: kallithea/model/validators.py:626 msgid "This username or user group name is not valid" msgstr "ユーザー名かユーザーグループが不正です" -#: rhodecode/model/validators.py:652 +#: kallithea/model/validators.py:719 msgid "This is not a valid path" msgstr "不正なパスです" -#: rhodecode/model/validators.py:667 +#: kallithea/model/validators.py:734 msgid "This e-mail address is already taken" msgstr "このメールアドレスはすでに取得されています" -#: rhodecode/model/validators.py:687 +#: kallithea/model/validators.py:754 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "メールアドレス \"%(email)s\" は存在しません" -#: rhodecode/model/validators.py:724 +#: kallithea/model/validators.py:791 msgid "" -"The LDAP Login attribute of the CN must be specified - this is the name of " -"the attribute that is equivalent to \"username\"" +"The LDAP Login attribute of the CN must be specified - this is the name " +"of the attribute that is equivalent to \"username\"" msgstr "LDAPのこのCNに対するログイン属性は必須です。 - これは \"ユーザー名\" と同じです" -#: rhodecode/model/validators.py:737 +#: kallithea/model/validators.py:804 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" msgstr "リビジョン %(revs)s はすでにプルリクエストの一部かステータスが設定されています" -#: rhodecode/model/validators.py:769 +#: kallithea/model/validators.py:836 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "有効なIPv4かIPv6のアドレスを入力してください" -#: rhodecode/model/validators.py:770 -#, python-format -msgid "" -"The network size (bits) must be within the range of 0-32 (not %(bits)r)" -msgstr "" - -#: rhodecode/model/validators.py:803 +#: kallithea/model/validators.py:837 +#, python-format +msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" +msgstr "ネットワークサイズ (bits) は0-32の範囲にする必要があります ( %(bits)r は不正です)" + +#: kallithea/model/validators.py:870 msgid "Key name can only consist of letters, underscore, dash or numbers" msgstr "キー名はアルファベット、アンダースコア(_)、ピリオド(.)、ダッシュ(-)、数字しか使えません。" -#: rhodecode/model/validators.py:817 +#: kallithea/model/validators.py:884 msgid "Filename cannot be inside a directory" +msgstr "ファイル名はディレクトリ内にすることはできません" + +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "%(loaded)s プラグインと %(next_to_load)s プラグインで同じ名前が使われています" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" msgstr "" -#: rhodecode/templates/index.html:5 +#: kallithea/templates/index.html:5 msgid "Dashboard" msgstr "ダッシュボード" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/repo_switcher_list.html:4 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/users/user_edit_my_account.html:31 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/bookmarks/bookmarks.html:9 -#: rhodecode/templates/branches/branches.html:9 -#: rhodecode/templates/journal/journal.html:9 -#: rhodecode/templates/journal/journal.html:46 -#: rhodecode/templates/journal/journal.html:47 -#: rhodecode/templates/tags/tags.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 msgid "quick filter..." msgstr "クイックフィルタ..." -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/admin/repos/repos.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 msgid "repositories" msgstr "リポジトリ" -#: rhodecode/templates/index_base.html:13 -#: rhodecode/templates/index_base.html:18 -#: rhodecode/templates/admin/repos/repo_add.html:5 -#: rhodecode/templates/admin/repos/repos.html:22 -msgid "Add repository" +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" msgstr "リポジトリを追加" -#: rhodecode/templates/index_base.html:15 -#: rhodecode/templates/index_base.html:20 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:31 -msgid "Add group" -msgstr "グループを追加" - -#: rhodecode/templates/index_base.html:27 -msgid "Edit group" -msgstr "グループを編集" - -#: rhodecode/templates/index_base.html:27 +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "リポジトリグループを追加" + +#: kallithea/templates/index_base.html:32 msgid "You have admin right to this group, and can edit it" -msgstr "" - -#: rhodecode/templates/index_base.html:40 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:33 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:38 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:43 -#: rhodecode/templates/admin/users_groups/users_group_add.html:32 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 -#: rhodecode/templates/admin/users_groups/users_groups.html:37 -msgid "Group name" +msgstr "管理者権限をもっているため編集できます" + +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "リポジトリグループを編集" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" msgstr "グループ名" -#: rhodecode/templates/index_base.html:41 -#: rhodecode/templates/index_base.html:123 -#: rhodecode/templates/admin/repos/repo_add_base.html:56 -#: rhodecode/templates/admin/repos/repo_edit.html:68 -#: rhodecode/templates/admin/repos/repos.html:75 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:42 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:47 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:44 -#: rhodecode/templates/email_templates/changeset_comment.html:9 -#: rhodecode/templates/email_templates/pull_request.html:9 -#: rhodecode/templates/forks/fork.html:56 -#: rhodecode/templates/pullrequests/pullrequest.html:43 -#: rhodecode/templates/pullrequests/pullrequest_show.html:81 -#: rhodecode/templates/summary/summary.html:106 +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 msgid "Description" msgstr "説明" -#: rhodecode/templates/index_base.html:51 -#: rhodecode/templates/admin/permissions/permissions.html:55 -#: rhodecode/templates/admin/repos/repo_add_base.html:29 -#: rhodecode/templates/admin/repos/repo_edit.html:50 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:57 -#: rhodecode/templates/forks/fork.html:47 -msgid "Repository group" -msgstr "リポジトリグループ" - -#: rhodecode/templates/index_base.html:121 -#: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit.html:32 -#: rhodecode/templates/admin/repos/repos.html:73 -#: rhodecode/templates/admin/users/user_edit_my_account.html:172 -#: rhodecode/templates/base/perms_summary.html:37 -#: rhodecode/templates/bookmarks/bookmarks.html:48 -#: rhodecode/templates/bookmarks/bookmarks_data.html:6 -#: rhodecode/templates/branches/branches.html:47 -#: rhodecode/templates/branches/branches_data.html:6 -#: rhodecode/templates/files/files_browser.html:47 -#: rhodecode/templates/journal/journal.html:193 -#: rhodecode/templates/journal/journal.html:283 -#: rhodecode/templates/summary/summary.html:55 -#: rhodecode/templates/summary/summary.html:124 -#: rhodecode/templates/tags/tags.html:48 -#: rhodecode/templates/tags/tags_data.html:6 +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 msgid "Name" msgstr "名前" -#: rhodecode/templates/index_base.html:124 +#: kallithea/templates/index_base.html:129 msgid "Last Change" msgstr "最後の変更点" -#: rhodecode/templates/index_base.html:126 -#: rhodecode/templates/admin/repos/repos.html:76 -#: rhodecode/templates/admin/users/user_edit_my_account.html:174 -#: rhodecode/templates/journal/journal.html:195 -#: rhodecode/templates/journal/journal.html:285 +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 msgid "Tip" msgstr "Tip" -#: rhodecode/templates/index_base.html:128 -#: rhodecode/templates/admin/repos/repo_edit.html:114 -#: rhodecode/templates/admin/repos/repos.html:78 +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 msgid "Owner" msgstr "所有者" -#: rhodecode/templates/index_base.html:136 -#: rhodecode/templates/admin/repos/repos.html:86 -#: rhodecode/templates/admin/users/user_edit_my_account.html:183 -#: rhodecode/templates/admin/users/users.html:107 -#: rhodecode/templates/bookmarks/bookmarks.html:74 -#: rhodecode/templates/branches/branches.html:73 -#: rhodecode/templates/journal/journal.html:204 -#: rhodecode/templates/journal/journal.html:294 -#: rhodecode/templates/tags/tags.html:74 +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 msgid "Click to sort ascending" msgstr "昇順で並び換え" -#: rhodecode/templates/index_base.html:137 -#: rhodecode/templates/admin/repos/repos.html:87 -#: rhodecode/templates/admin/users/user_edit_my_account.html:184 -#: rhodecode/templates/admin/users/users.html:108 -#: rhodecode/templates/bookmarks/bookmarks.html:75 -#: rhodecode/templates/branches/branches.html:74 -#: rhodecode/templates/journal/journal.html:205 -#: rhodecode/templates/journal/journal.html:295 -#: rhodecode/templates/tags/tags.html:75 +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 msgid "Click to sort descending" msgstr "降順で並び替え" -#: rhodecode/templates/index_base.html:138 +#: kallithea/templates/index_base.html:143 msgid "No repositories found." msgstr "リポジトリが見つかりません" -#: rhodecode/templates/index_base.html:139 -#: rhodecode/templates/admin/repos/repos.html:89 -#: rhodecode/templates/admin/users/user_edit_my_account.html:186 -#: rhodecode/templates/admin/users/users.html:110 -#: rhodecode/templates/bookmarks/bookmarks.html:77 -#: rhodecode/templates/branches/branches.html:76 -#: rhodecode/templates/journal/journal.html:207 -#: rhodecode/templates/journal/journal.html:297 -#: rhodecode/templates/tags/tags.html:77 +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 msgid "Data error." msgstr "データエラー" -#: rhodecode/templates/index_base.html:140 -#: rhodecode/templates/admin/repos/repos.html:90 -#: rhodecode/templates/admin/users/user_edit_my_account.html:58 -#: rhodecode/templates/admin/users/user_edit_my_account.html:187 -#: rhodecode/templates/admin/users/users.html:111 -#: rhodecode/templates/bookmarks/bookmarks.html:78 -#: rhodecode/templates/branches/branches.html:77 -#: rhodecode/templates/journal/journal.html:208 -#: rhodecode/templates/journal/journal.html:298 -#: rhodecode/templates/tags/tags.html:78 +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 msgid "Loading..." msgstr "読み込み中..." -#: rhodecode/templates/login.html:5 rhodecode/templates/base/base.html:239 +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 msgid "Log In" msgstr "ログイン" -#: rhodecode/templates/login.html:21 +#: kallithea/templates/login.html:30 #, python-format msgid "Log In to %s" msgstr "%s へログイン" -#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20 -#: rhodecode/templates/admin/admin_log.html:5 -#: rhodecode/templates/admin/users/user_add.html:32 -#: rhodecode/templates/admin/users/user_edit.html:57 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:31 -#: rhodecode/templates/admin/users/users.html:77 -#: rhodecode/templates/base/base.html:215 -#: rhodecode/templates/summary/summary.html:123 +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 msgid "Username" msgstr "ユーザー名" -#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29 -#: rhodecode/templates/admin/ldap/ldap.html:46 -#: rhodecode/templates/admin/users/user_add.html:41 -#: rhodecode/templates/base/base.html:224 +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 msgid "Password" msgstr "パスワード" -#: rhodecode/templates/login.html:50 +#: kallithea/templates/login.html:62 msgid "Remember me" msgstr "次回から自動的にサインイン" -#: rhodecode/templates/login.html:54 +#: kallithea/templates/login.html:66 msgid "Sign In" msgstr "サインイン" -#: rhodecode/templates/login.html:60 +#: kallithea/templates/login.html:72 msgid "Forgot your password ?" -msgstr "パスワードを忘れた場合はこちら" - -#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:235 +msgstr "パスワードを忘れた?" + +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 msgid "Don't have an account ?" -msgstr "アカウントを持っていない場合はこちら" - -#: rhodecode/templates/password_reset.html:5 +msgstr "アカウントを持っていない?" + +#: kallithea/templates/password_reset.html:5 msgid "Password Reset" msgstr "パスワードリセット" -#: rhodecode/templates/password_reset.html:11 -msgid "Reset your password to" -msgstr "パスワードリセット" - -#: rhodecode/templates/password_reset.html:21 -msgid "Email address" +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "パスワードを %s にリセットします" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "パスワードをリセット" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" msgstr "メールアドレス" -#: rhodecode/templates/password_reset.html:30 -msgid "Reset my password" -msgstr "パスワードをリセットする" - -#: rhodecode/templates/password_reset.html:31 +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "キャプチャ" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "パスワードリセットのメールを送信" + +#: kallithea/templates/password_reset.html:64 msgid "Password reset link will be send to matching email address" msgstr "該当するメールアドレスにパスワードリセットのリンクを送信します" -#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74 +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 msgid "Sign Up" msgstr "サインアップ" -#: rhodecode/templates/register.html:11 -msgid "Sign Up to" -msgstr "サインアップ" - -#: rhodecode/templates/register.html:38 +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "%s へサインアップ" + +#: kallithea/templates/register.html:58 msgid "Re-enter password" msgstr "パスワード再入力" -#: rhodecode/templates/register.html:47 -#: rhodecode/templates/admin/users/user_add.html:59 -#: rhodecode/templates/admin/users/user_edit.html:97 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:62 +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 msgid "First Name" msgstr "名前" -#: rhodecode/templates/register.html:56 -#: rhodecode/templates/admin/users/user_add.html:68 -#: rhodecode/templates/admin/users/user_edit.html:106 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:71 +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 msgid "Last Name" msgstr "名字" -#: rhodecode/templates/register.html:65 -#: rhodecode/templates/admin/users/user_add.html:77 -#: rhodecode/templates/admin/users/user_edit.html:115 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:80 -#: rhodecode/templates/summary/summary.html:125 +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 msgid "Email" msgstr "メールアドレス" -#: rhodecode/templates/register.html:76 +#: kallithea/templates/register.html:108 msgid "Your account will be activated right after registration" -msgstr "アカウントは登録後にアクティブになります" - -#: rhodecode/templates/register.html:78 +msgstr "アカウントは登録後すぐに利用できます" + +#: kallithea/templates/register.html:110 msgid "Your account must wait for activation by administrator" -msgstr "アカウントは管理者のアクティベーションを待つ必要があります" - -#: rhodecode/templates/repo_switcher_list.html:10 -#: rhodecode/templates/admin/defaults/defaults.html:44 -#: rhodecode/templates/admin/repos/repo_add_base.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:78 -#: rhodecode/templates/data_table/_dt_elements.html:61 -#: rhodecode/templates/summary/summary.html:77 -msgid "Private repository" -msgstr "非公開リポジトリ" - -#: rhodecode/templates/repo_switcher_list.html:12 -#: rhodecode/templates/data_table/_dt_elements.html:63 -#: rhodecode/templates/summary/summary.html:79 -msgid "Public repository" -msgstr "公開リポジトリ" - -#: rhodecode/templates/switch_to_list.html:10 -#: rhodecode/templates/branches/branches_data.html:57 +msgstr "アカウントは管理者のアクティベートを待つ必要があります" + +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 msgid "There are no branches yet" msgstr "まだブランチがありません" -#: rhodecode/templates/switch_to_list.html:22 -#: rhodecode/templates/tags/tags_data.html:38 +#: kallithea/templates/switch_to_list.html:16 +msgid "Closed Branches" +msgstr "閉鎖済みブランチ" + +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 msgid "There are no tags yet" msgstr "まだタグがありません" -#: rhodecode/templates/switch_to_list.html:35 -#: rhodecode/templates/bookmarks/bookmarks_data.html:37 +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 msgid "There are no bookmarks yet" msgstr "まだブックマークがありません" -#: rhodecode/templates/admin/admin.html:5 -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/base/base.html:73 +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 msgid "Admin journal" msgstr "管理者ジャーナル" -#: rhodecode/templates/admin/admin.html:10 +#: kallithea/templates/admin/admin.html:13 msgid "journal filter..." msgstr "ジャーナルフィルタ..." -#: rhodecode/templates/admin/admin.html:12 -#: rhodecode/templates/journal/journal.html:11 +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 msgid "filter" msgstr "フィルタ" -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 #, python-format msgid "%s entry" msgid_plural "%s entries" -msgstr[0] "%s エントリ" - -#: rhodecode/templates/admin/admin_log.html:6 -#: rhodecode/templates/admin/repos/repos.html:79 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46 -#: rhodecode/templates/admin/users/user_edit_my_account.html:176 -#: rhodecode/templates/admin/users/users.html:87 -#: rhodecode/templates/admin/users_groups/users_groups.html:40 -#: rhodecode/templates/journal/journal.html:197 -#: rhodecode/templates/journal/journal.html:287 +msgstr[0] "%s 個のエントリ" + +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 msgid "Action" msgstr "アクション" -#: rhodecode/templates/admin/admin_log.html:7 -#: rhodecode/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" msgstr "リポジトリ" -#: rhodecode/templates/admin/admin_log.html:8 -#: rhodecode/templates/bookmarks/bookmarks.html:49 -#: rhodecode/templates/bookmarks/bookmarks_data.html:7 -#: rhodecode/templates/branches/branches.html:48 -#: rhodecode/templates/branches/branches_data.html:7 -#: rhodecode/templates/tags/tags.html:49 -#: rhodecode/templates/tags/tags_data.html:7 +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 msgid "Date" msgstr "日時" -#: rhodecode/templates/admin/admin_log.html:9 +#: kallithea/templates/admin/admin_log.html:9 msgid "From IP" msgstr "アクセス元IPアドレス" -#: rhodecode/templates/admin/admin_log.html:63 +#: kallithea/templates/admin/admin_log.html:63 msgid "No actions yet" msgstr "まだアクションがありません" -#: rhodecode/templates/admin/defaults/defaults.html:5 -#: rhodecode/templates/admin/defaults/defaults.html:25 +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "認証設定" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "認証" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "認証プラグイン" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "有効なプラグイン" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "" +"Comma separated list of plugins. Order of plugins is also order in which " +"Kallithea will try to authenticate user" +msgstr "カンマ区切りのプラグインの一覧です。プラグインの並び順はKallitheaがユーザー認証を試す順番でもあります。" + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "有効な組み込みプラグイン" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "有効" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "無効" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "保存" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "プラグイン" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 msgid "Repositories defaults" msgstr "リポジトリのデフォルト設定" -#: rhodecode/templates/admin/defaults/defaults.html:11 -#: rhodecode/templates/base/base.html:80 +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 msgid "Defaults" msgstr "デフォルト設定" -#: rhodecode/templates/admin/defaults/defaults.html:35 -#: rhodecode/templates/admin/repos/repo_add_base.html:38 +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 msgid "Type" -msgstr "リポジトリのタイプ" - -#: rhodecode/templates/admin/defaults/defaults.html:48 -#: rhodecode/templates/admin/repos/repo_add_base.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:82 -#: rhodecode/templates/forks/fork.html:69 +msgstr "リポジトリの種別" + +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "非公開リポジトリ" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 msgid "" "Private repositories are only visible to people explicitly added as " "collaborators." msgstr "非公開リポジトリはコラボレーターとして明示的に追加された人でないと見つけられません" -#: rhodecode/templates/admin/defaults/defaults.html:55 -#: rhodecode/templates/admin/repos/repo_edit.html:87 +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 msgid "Enable statistics" msgstr "統計を有効にする" -#: rhodecode/templates/admin/defaults/defaults.html:59 -#: rhodecode/templates/admin/repos/repo_edit.html:91 +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." msgstr "概要ページの統計ウィンドウを有効にします" -#: rhodecode/templates/admin/defaults/defaults.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:96 +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 msgid "Enable downloads" msgstr "ダウンロードを有効にする" -#: rhodecode/templates/admin/defaults/defaults.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:100 +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." msgstr "概要ページのダウンロードメニューを有効にします" -#: rhodecode/templates/admin/defaults/defaults.html:75 -#: rhodecode/templates/admin/repos/repo_edit.html:105 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:64 +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 msgid "Enable locking" msgstr "ロックを有効にする" -#: rhodecode/templates/admin/defaults/defaults.html:79 -#: rhodecode/templates/admin/repos/repo_edit.html:109 +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 msgid "Enable lock-by-pulling on repository." msgstr "リポジトリのpullのロックを有効にします" -#: rhodecode/templates/admin/defaults/defaults.html:84 -#: rhodecode/templates/admin/ldap/ldap.html:89 -#: rhodecode/templates/admin/permissions/permissions.html:122 -#: rhodecode/templates/admin/repos/repo_edit.html:141 -#: rhodecode/templates/admin/repos/repo_edit.html:166 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:72 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:96 -#: rhodecode/templates/admin/settings/hooks.html:73 -#: rhodecode/templates/admin/users/user_add.html:94 -#: rhodecode/templates/admin/users/user_edit.html:140 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:88 -#: rhodecode/templates/admin/users_groups/users_group_add.html:49 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:143 -#: rhodecode/templates/base/default_perms_box.html:53 -msgid "Save" -msgstr "保存" - -#: rhodecode/templates/admin/gists/index.html:5 -#: rhodecode/templates/base/base.html:299 -msgid "Gists" +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "Gistを編集" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "" +"Gist was update since you started editing. Copy your changes and click " +"%(here)s to reload new version." msgstr "" - -#: rhodecode/templates/admin/gists/index.html:10 +"編集開始後にGistが更新されています。あなたの変更箇所をコピーしておき、 %(here)s " +"をクリックして新しいバージョンを読み込みなおしてください。" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "Gist の説明..." + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "Gist 有効期間" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "失効" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "無し" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "plain" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "Gistを更新" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "キャンセル" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 #, python-format msgid "Private Gists for user %s" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:12 +msgstr "ユーザー %s の非公開 Gists" + +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 #, python-format msgid "Public Gists for user %s" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:14 +msgstr "ユーザー %s の公開 Gists" + +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 msgid "Public Gists" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:31 -#: rhodecode/templates/admin/gists/show.html:24 -#: rhodecode/templates/base/base.html:302 -msgid "Create new gist" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:48 +msgstr "公開 Gists" + +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "新しい Gist を作成" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 msgid "Created" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/index.html:53 -#: rhodecode/templates/admin/gists/show.html:43 -#: rhodecode/templates/admin/gists/show.html:45 -msgid "Expires" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/show.html:43 -msgid "never" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:68 +msgstr "作成日" + +#: kallithea/templates/admin/gists/index.html:77 msgid "There are no gists yet" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:5 -#: rhodecode/templates/admin/gists/new.html:16 -msgid "New gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:37 -msgid "Gist description ..." -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:52 -msgid "Create private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:53 -msgid "Create public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:54 -#: rhodecode/templates/admin/permissions/permissions.html:123 -#: rhodecode/templates/admin/permissions/permissions.html:185 -#: rhodecode/templates/admin/repos/repo_edit.html:142 -#: rhodecode/templates/admin/repos/repo_edit.html:167 -#: rhodecode/templates/admin/repos/repo_edit.html:381 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:97 -#: rhodecode/templates/admin/settings/settings.html:115 -#: rhodecode/templates/admin/settings/settings.html:196 -#: rhodecode/templates/admin/settings/settings.html:288 -#: rhodecode/templates/admin/users/user_edit.html:141 -#: rhodecode/templates/admin/users/user_edit.html:198 -#: rhodecode/templates/admin/users/user_edit.html:246 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:89 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:144 -#: rhodecode/templates/base/default_perms_box.html:54 -#: rhodecode/templates/files/files_add.html:80 -#: rhodecode/templates/files/files_edit.html:66 -#: rhodecode/templates/pullrequests/pullrequest.html:86 +msgstr "まだgistがありません" + +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "Gistを新規作成" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "ファイルに名前をつける..." + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "非公開 Gist を作成" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "公開 Gist を作成" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 msgid "Reset" msgstr "リセット" -#: rhodecode/templates/admin/gists/show.html:5 -msgid "gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:9 +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 msgid "Gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:36 -msgid "Public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:38 -msgid "Private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:54 -#: rhodecode/templates/admin/repos/repo_edit.html:299 -#: rhodecode/templates/changeset/changeset_file_comment.html:40 +msgstr "Gist" + +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "URL" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "公開 Gist" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "非公開 Gist" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 msgid "Delete" msgstr "削除" -#: rhodecode/templates/admin/gists/show.html:54 -msgid "Confirm to delete this gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:63 -#: rhodecode/templates/admin/gists/show.html:84 -#: rhodecode/templates/files/files_edit.html:48 -#: rhodecode/templates/files/files_source.html:25 -#: rhodecode/templates/files/files_source.html:55 -msgid "Show as raw" -msgstr "元のファイルを表示" - -#: rhodecode/templates/admin/gists/show.html:71 +#: kallithea/templates/admin/gists/show.html:59 +msgid "Confirm to delete this Gist" +msgstr "このGistを削除してもよろしいですか?" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "編集" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "Raw形式で表示" + +#: kallithea/templates/admin/gists/show.html:76 msgid "created" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:5 -msgid "LDAP administration" -msgstr "LDAP管理" - -#: rhodecode/templates/admin/ldap/ldap.html:11 -#: rhodecode/templates/admin/users/users.html:86 -#: rhodecode/templates/base/base.html:79 -msgid "LDAP" -msgstr "LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:28 -msgid "Connection settings" -msgstr "接続設定" - -#: rhodecode/templates/admin/ldap/ldap.html:30 -msgid "Enable LDAP" -msgstr "LDAPを有効にする" - -#: rhodecode/templates/admin/ldap/ldap.html:34 -msgid "Host" -msgstr "ホスト" - -#: rhodecode/templates/admin/ldap/ldap.html:38 -msgid "Port" -msgstr "ポート" - -#: rhodecode/templates/admin/ldap/ldap.html:42 -msgid "Account" +msgstr "作成日" + +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "Raw形式で表示" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "アカウント" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" msgstr "アカウント" -#: rhodecode/templates/admin/ldap/ldap.html:50 -msgid "Connection security" -msgstr "接続のセキュリティ" - -#: rhodecode/templates/admin/ldap/ldap.html:54 -msgid "Certificate Checks" -msgstr "証明書チェック" - -#: rhodecode/templates/admin/ldap/ldap.html:57 -msgid "Search settings" -msgstr "検索設定" - -#: rhodecode/templates/admin/ldap/ldap.html:59 -msgid "Base DN" -msgstr "Base DN" - -#: rhodecode/templates/admin/ldap/ldap.html:63 -msgid "LDAP Filter" -msgstr "LDAPフィルター" - -#: rhodecode/templates/admin/ldap/ldap.html:67 -msgid "LDAP Search Scope" -msgstr "LDAP検索範囲" - -#: rhodecode/templates/admin/ldap/ldap.html:70 -msgid "Attribute mappings" -msgstr "属性マッピング" - -#: rhodecode/templates/admin/ldap/ldap.html:72 -msgid "Login Attribute" -msgstr "ログイン属性" - -#: rhodecode/templates/admin/ldap/ldap.html:76 -msgid "First Name Attribute" -msgstr "名前(First Name)属性" - -#: rhodecode/templates/admin/ldap/ldap.html:80 -msgid "Last Name Attribute" -msgstr "名字(Last Name)属性" - -#: rhodecode/templates/admin/ldap/ldap.html:84 -msgid "E-mail Attribute" -msgstr "メールアドレス属性" - -#: rhodecode/templates/admin/notifications/notifications.html:5 -#: rhodecode/templates/admin/notifications/notifications.html:9 +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "プロフィール" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "APIキー" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "メールアドレス" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "リポジトリ" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "ウォッチ中" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "プルリクエスト" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "権限" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "ビルトイン" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "失効" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "このAPIキーをリセットしてもよろしいですか?: %s" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "リセット" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "失効済み" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "このAPIキーを削除してもよろしいですか?: %s" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "削除" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "API キーが指定されていません" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "新しいAPIキー" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "追加" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "プライマリ" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "削除" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "このメールアドレスを削除してもよろしいですか? : %s" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "追加のメールアドレスはありません" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "新しいメールアドレス" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "新しいパスワード" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "アバターを変更できます : " + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "メールアドレス:" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "アバターは無効です" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "メールアドレスがありません。更新してください。" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "現在の IP" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "" +"Your user is in an external Source of Record; some details cannot be " +"managed here" +msgstr "ユーザーは外部の Source of Record に属しているため、ここでは詳細を管理できません" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "クローズしたプルリクエストを表示" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "あなたが作成したプルリクエスト" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "プルリクエスト #%s %s に作成" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "クローズ" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "このプルリクエストを削除してもよろしいですか?" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "まだありません" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "あなたがレビュアーとして参加しているプルリクエスト" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "プルリクエスト #%s %s によって %s に作成" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "あなたが所有者のリポジトリ" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "レコードが見つかりません" + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "あなたがウォッチしているリポジトリ" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 msgid "My Notifications" msgstr "通知" -#: rhodecode/templates/admin/notifications/notifications.html:29 +#: kallithea/templates/admin/notifications/notifications.html:32 msgid "All" msgstr "すべて" -#: rhodecode/templates/admin/notifications/notifications.html:30 +#: kallithea/templates/admin/notifications/notifications.html:33 msgid "Comments" msgstr "コメント" -#: rhodecode/templates/admin/notifications/notifications.html:31 -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:8 -msgid "Pull requests" +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" msgstr "プルリクエスト" -#: rhodecode/templates/admin/notifications/notifications.html:35 +#: kallithea/templates/admin/notifications/notifications.html:38 msgid "Mark all read" msgstr "すべて既読にする" -#: rhodecode/templates/admin/notifications/notifications_data.html:39 +#: kallithea/templates/admin/notifications/notifications_data.html:40 msgid "No notifications here yet" -msgstr "通知はまだありません" - -#: rhodecode/templates/admin/notifications/show_notification.html:5 -#: rhodecode/templates/admin/notifications/show_notification.html:11 +msgstr "まだ通知がありません" + +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 msgid "Show notification" msgstr "通知を表示" -#: rhodecode/templates/admin/notifications/show_notification.html:9 -#: rhodecode/templates/base/base.html:253 +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 msgid "Notifications" msgstr "通知" -#: rhodecode/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:5 msgid "Permissions administration" msgstr "権限管理" -#: rhodecode/templates/admin/permissions/permissions.html:11 -#: rhodecode/templates/admin/repos/repo_edit.html:151 -#: rhodecode/templates/admin/repos/repo_edit.html:158 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:81 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:88 -#: rhodecode/templates/admin/users/user_edit.html:150 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:129 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:136 -#: rhodecode/templates/base/base.html:78 +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 msgid "Permissions" msgstr "権限設定" -#: rhodecode/templates/admin/permissions/permissions.html:24 -msgid "Default permissions" -msgstr "デフォルトの権限" - -#: rhodecode/templates/admin/permissions/permissions.html:31 +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "全般" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "IPアドレスのホワイトリスト" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "概要" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 msgid "Anonymous access" msgstr "匿名アクセス" -#: rhodecode/templates/admin/permissions/permissions.html:49 +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without need to log in. Anonymous users use %s " +"user permissions" +msgstr "ログインしなくても Kallithea にアクセスできるようにします。匿名ユーザーは %s ユーザーパーミッションを使います" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 msgid "" "All default permissions on each repository will be reset to chosen " -"permission, note that all custom default permission on repositories will be " -"lost" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:50 -#: rhodecode/templates/admin/permissions/permissions.html:63 -#: rhodecode/templates/admin/permissions/permissions.html:77 +"permission, note that all custom default permission on repositories will " +"be lost" +msgstr "選択したパーミッションで、各リポジトリのデフォルトパーミッションをリセットします。各リポジトリの既存のカスタムデフォルトパーミッション設定は無くなるので注意してください" + +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 msgid "Overwrite existing settings" msgstr "現在の設定を上書きする" -#: rhodecode/templates/admin/permissions/permissions.html:62 +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "リポジトリグループ" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 msgid "" "All default permissions on each repository group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:69 +msgstr "選択したパーミッションで、各リポジトリグループのデフォルトパーミッションをリセットします。各リポジトリグループの既存のカスタムデフォルトパーミッション設定は無くなるので注意してください" + +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 msgid "User group" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:76 +msgstr "ユーザーグループ" + +#: kallithea/templates/admin/permissions/permissions_globals.html:53 msgid "" "All default permissions on each user group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:83 +msgstr "選択したパーミッションで、各ユーザーグループのデフォルトパーミッションをリセットします。各ユーザーグループの既存のカスタムデフォルトパーミッション設定は無くなるので注意してください" + +#: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" msgstr "リポジトリ作成" -#: rhodecode/templates/admin/permissions/permissions.html:91 +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "グループ書き込み権限でのリポジトリ作成" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "" +"Write permission to repository groups allows creating repositories inside" +" that group" +msgstr "リポジトリグループに書き込みパーミッションを付与すると、グループ内にリポジトリを作成できるようになります" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 msgid "User group creation" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:99 +msgstr "ユーザーグループ作成" + +#: kallithea/templates/admin/permissions/permissions_globals.html:85 msgid "Repository forking" -msgstr "リポジトリフォーク" - -#: rhodecode/templates/admin/permissions/permissions.html:107 +msgstr "リポジトリのフォーク" + +#: kallithea/templates/admin/permissions/permissions_globals.html:93 msgid "Registration" -msgstr "登録" - -#: rhodecode/templates/admin/permissions/permissions.html:115 +msgstr "新規登録" + +#: kallithea/templates/admin/permissions/permissions_globals.html:101 msgid "External auth account activation" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:133 -msgid "Default User Permissions" -msgstr "デフォルトのユーザー権限" - -#: rhodecode/templates/admin/permissions/permissions.html:144 -#: rhodecode/templates/admin/users/user_edit.html:207 -msgid "Allowed IP addresses" -msgstr "許可するIPアドレス" - -#: rhodecode/templates/admin/permissions/permissions.html:158 -#: rhodecode/templates/admin/repos/repo_edit.html:340 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#: rhodecode/templates/admin/users/user_edit.html:175 -#: rhodecode/templates/admin/users/user_edit.html:220 -#: rhodecode/templates/admin/users_groups/users_groups.html:54 -#: rhodecode/templates/data_table/_dt_elements.html:122 -#: rhodecode/templates/data_table/_dt_elements.html:136 -msgid "delete" -msgstr "削除" - -#: rhodecode/templates/admin/permissions/permissions.html:159 -#: rhodecode/templates/admin/users/user_edit.html:221 +msgstr "外部認証アカウントのアクティベート" + +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "全てのユーザーに設定されるデフォルトのIPアドレスのホワイトリスト" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 #, python-format msgid "Confirm to delete this ip: %s" -msgstr "このIPアドレスを削除してよろしいですか: %s" - -#: rhodecode/templates/admin/permissions/permissions.html:165 -#: rhodecode/templates/admin/users/user_edit.html:227 +msgstr "このIPアドレスを削除してもよろしいですか? : %s" + +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 msgid "All IP addresses are allowed" msgstr "すべてのIPアドレスが許可されています" -#: rhodecode/templates/admin/permissions/permissions.html:176 -#: rhodecode/templates/admin/users/user_edit.html:238 +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" msgstr "新しいIPアドレス" -#: rhodecode/templates/admin/permissions/permissions.html:184 -#: rhodecode/templates/admin/repos/repo_add_base.html:73 -#: rhodecode/templates/admin/repos/repo_edit.html:380 -#: rhodecode/templates/admin/users/user_edit.html:197 -#: rhodecode/templates/admin/users/user_edit.html:245 -msgid "Add" -msgstr "追加" - -#: rhodecode/templates/admin/repos/repo_add.html:12 -#: rhodecode/templates/admin/repos/repo_add.html:16 -#: rhodecode/templates/base/base.html:74 rhodecode/templates/base/base.html:88 -#: rhodecode/templates/base/base.html:116 -#: rhodecode/templates/base/base.html:275 -msgid "Repositories" -msgstr "リポジトリ" - -#: rhodecode/templates/admin/repos/repo_add.html:19 -msgid "Add new" -msgstr "新規追加" - -#: rhodecode/templates/admin/repos/repo_add_base.html:20 -#: rhodecode/templates/summary/summary.html:96 -#: rhodecode/templates/summary/summary.html:97 -msgid "Clone from" -msgstr "クローン元" - -#: rhodecode/templates/admin/repos/repo_add_base.html:24 -#: rhodecode/templates/admin/repos/repo_edit.html:45 -msgid "Optional http[s] url from which repository should be cloned." -msgstr "オプション:クローンするリポジトリのHTTP[S]のURLを指定します" - -#: rhodecode/templates/admin/repos/repo_add_base.html:33 -#: rhodecode/templates/forks/fork.html:51 -msgid "Optionaly select a group to put this repository into." -msgstr "オプション:このリポジトリが属するグループを選択します" - -#: rhodecode/templates/admin/repos/repo_add_base.html:42 -msgid "Type of repository to create." -msgstr "作成するリポジトリのタイプを指定します" - -#: rhodecode/templates/admin/repos/repo_add_base.html:47 -#: rhodecode/templates/admin/repos/repo_edit.html:59 -#: rhodecode/templates/forks/fork.html:38 -msgid "Landing revision" -msgstr "ランディングリビジョン" - -#: rhodecode/templates/admin/repos/repo_add_base.html:51 -#: rhodecode/templates/admin/repos/repo_edit.html:63 -#: rhodecode/templates/forks/fork.html:42 -msgid "Default revision for files page, downloads, whoosh and readme" -msgstr "ファイルページ、ダウンロード、検索、READMEのデフォルトのリビジョンを指定します" - -#: rhodecode/templates/admin/repos/repo_add_base.html:60 -#: rhodecode/templates/admin/repos/repo_edit.html:72 -#: rhodecode/templates/forks/fork.html:60 -msgid "" -"Keep it short and to the point. Use a README file for longer descriptions." -msgstr "短く要点を絞ってください。長い説明にはREADMEファイルを利用してください。" - -#: rhodecode/templates/admin/repos/repo_edit.html:8 -msgid "Edit repository" -msgstr "リポジトリを編集" - -#: rhodecode/templates/admin/repos/repo_edit.html:12 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:11 -#: rhodecode/templates/base/base.html:81 -#: rhodecode/templates/base/base.html:134 -#: rhodecode/templates/summary/summary.html:212 +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "デフォルトのユーザー権限の概要" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "リポジトリグループを追加" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "リポジトリグループ" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "グループ名" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "親グループ" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "親グループのパーミッションをコピー" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "親のリポジトリグループにセットされているパーミッションをコピーします。" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "%s リポジトリグループ 設定" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "リポジトリグループ" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "子グループを追加" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 msgid "Settings" msgstr "設定" -#: rhodecode/templates/admin/repos/repo_edit.html:36 -msgid "Non-changeable id" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:41 -msgid "Clone uri" -msgstr "クローンURI" - -#: rhodecode/templates/admin/repos/repo_edit.html:54 -msgid "Optional select a group to put this repository into." -msgstr "オプション: このリポジトリを配置するグループを選択します" - -#: rhodecode/templates/admin/repos/repo_edit.html:119 -msgid "Change owner of this repository." -msgstr "リポジトリの所有者を変更" - -#: rhodecode/templates/admin/repos/repo_edit.html:177 -msgid "Advanced settings" +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" msgstr "高度な設定" -#: rhodecode/templates/admin/repos/repo_edit.html:180 -msgid "Statistics" -msgstr "統計" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Reset current statistics" -msgstr "現在の統計情報をリセットする" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Confirm to remove current statistics" -msgstr "現在の統計情報をリセットしてもよろしいですか?" - -#: rhodecode/templates/admin/repos/repo_edit.html:187 -msgid "Fetched to rev" -msgstr "収集するリビジョン" - -#: rhodecode/templates/admin/repos/repo_edit.html:188 -msgid "Stats gathered" -msgstr "収集した統計情報" - -#: rhodecode/templates/admin/repos/repo_edit.html:196 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "リポジトリグループ: %s" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "トップレベルリポジトリ数" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "リポジトリ総数" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "子グループ数" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "作成日" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 +#, python-format +msgid "Confirm to delete this group: %s with %s repository" +msgid_plural "Confirm to delete this group: %s with %s repositories" +msgstr[0] "このグループを削除してもよろしいですか? : %s %s 個のリポジトリ" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "このリポジトリグループを削除" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "なし" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "読込" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "書込" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "管理" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "ユーザー/ユーザーグループ" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "default" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "取消" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "代理 admin" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "新規追加" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "子要素にも適用" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "両方" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "" +"Set or revoke permission to all children of that group, including non-" +"private repositories and other groups if selected." +msgstr "このグループに属する全ての子要素のパーミッションを設定または無効化します。選択されていれば、非公開でないリポジトリや他のリポジトリも対象に含みます。" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "" +"Enable lock-by-pulling on group. This option will be applied to all other" +" groups and repositories inside" +msgstr "グループのpullのロックを有効にします。このオプションはグループに含まれる全てのグループとリポジトリに適用されます。" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "%s Repository group dashboard" +msgstr "%s リポジトリグループダッシュボード" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "ホーム" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "と" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "リポジトリグループ管理" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "リポジトリグループ" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "トップレベルリポジトリ数" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "リポジトリを追加" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "既存のリポジトリを import しますか?" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "クローン元" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "オプション:クローンするリポジトリのHTTP[S]のURLを指定します" + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "短く要点を絞ってください。長い説明にはREADMEファイルを利用してください。" + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "オプション:このリポジトリが属するグループを選択します" + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "作成するリポジトリの種別を指定します" + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "ランディングリビジョン" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "ファイルページ、ダウンロード、全文検索インデックス、READMEなどの生成に使うデフォルトのリビジョン" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "%s Creating repository" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "リポジトリを作成中" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is beeing created, you will be redirected " +"when this process is finished.repo_name" +msgstr "リポジトリ \"%(repo_name)s\" を作成中です。処理を完了したらリダイレクトします。" + +#: kallithea/templates/admin/repos/repo_creating.html:42 +msgid "" +"We're sorry but error occured during this operation. Please check your " +"Kallithea server logs, or contact administrator." +msgstr "恐れいります。操作中にエラーが発生しました。 Kallithea サーバのログをチェックするか、管理者に問い合わせてください。" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, python-format +msgid "%s repository settings" +msgstr "%s リポジトリ設定" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "拡張フィールド" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "キャッシュ" + +#: kallithea/templates/admin/repos/repo_edit.html:58 msgid "Remote" msgstr "リモート" -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Pull changes from remote location" -msgstr "リモートから変更を取り込む" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Confirm to pull changes from remote side" -msgstr "リモートから変更を取り込んでもよろしいですか?" - -#: rhodecode/templates/admin/repos/repo_edit.html:211 -msgid "Cache" -msgstr "キャッシュ" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Invalidate repository cache" -msgstr "リポジトリのキャッシュを無効化" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Confirm to invalidate repository cache" -msgstr "リポジトリのキャッシュを無効化してもよろしいですか?" - -#: rhodecode/templates/admin/repos/repo_edit.html:218 -msgid "" -"Manually invalidate cache for this repository. On first access repository " -"will be cached again" -msgstr "このリポジトリのキャッシュを手動で無効化します。リポジトリへの初回アクセス時に再びキャッシュされます。" - -#: rhodecode/templates/admin/repos/repo_edit.html:223 -msgid "List of cached values" -msgstr "キャッシュしている値の一覧" - -#: rhodecode/templates/admin/repos/repo_edit.html:226 -msgid "Prefix" -msgstr "プレフィックス" - -#: rhodecode/templates/admin/repos/repo_edit.html:227 -msgid "Key" -msgstr "キー" - -#: rhodecode/templates/admin/repos/repo_edit.html:228 -#: rhodecode/templates/admin/users/user_add.html:86 -#: rhodecode/templates/admin/users/user_edit.html:124 -#: rhodecode/templates/admin/users/users.html:84 -#: rhodecode/templates/admin/users_groups/users_group_add.html:41 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 -#: rhodecode/templates/admin/users_groups/users_groups.html:39 -msgid "Active" -msgstr "アクティブ" - -#: rhodecode/templates/admin/repos/repo_edit.html:243 -#: rhodecode/templates/base/base.html:292 -#: rhodecode/templates/base/base.html:293 -msgid "Public journal" -msgstr "公開ジャーナル" - -#: rhodecode/templates/admin/repos/repo_edit.html:249 +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "統計" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "フォーク元" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "保存" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "このリポジトリをリスト中の他のリポジトリのフォークとして、手動で設定します" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "公開ジャーナルでの可視性" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 msgid "Remove from public journal" msgstr "公開ジャーナルから削除する" -#: rhodecode/templates/admin/repos/repo_edit.html:251 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 msgid "Add to public journal" -msgstr "公開ジャーナルに追加する" - -#: rhodecode/templates/admin/repos/repo_edit.html:256 +msgstr "公開ジャーナルへ追加" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 msgid "" -"All actions made on this repository will be accessible to everyone in public" -" journal" +"All actions made on this repository will be accessible to everyone in " +"public journal" msgstr "公開ジャーナルでは、このリポジトリに対して行った操作のすべてが公開されます" -#: rhodecode/templates/admin/repos/repo_edit.html:263 -msgid "Locking" +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" msgstr "ロック" -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Unlock locked repo" -msgstr "リポジトリのアンロック" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 msgid "Confirm to unlock repository" -msgstr "このリポジトリのロックを外しますか?" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Lock repo" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 +msgstr "このリポジトリのロックを解除しますか?" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "リポジトリのロックを解除" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 msgid "Confirm to lock repository" msgstr "このリポジトリをロックしますか?" -#: rhodecode/templates/admin/repos/repo_edit.html:272 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "リポジトリをロック" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 msgid "Repository is not locked" msgstr "リポジトリはロックされていません" -#: rhodecode/templates/admin/repos/repo_edit.html:277 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 msgid "" -"Force locking on repository. Works only when anonymous access is disabled" -msgstr "リポジトリを強制ロックします。匿名アクセスが無効になっている場合のみ動作します。" - -#: rhodecode/templates/admin/repos/repo_edit.html:284 -msgid "Set as fork of" -msgstr "フォーク元の設定" - -#: rhodecode/templates/admin/repos/repo_edit.html:289 -msgid "Set" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:293 -msgid "Manually set this repository as a fork of another from the list" -msgstr "このリポジトリをリスト中の他のリポジトリのフォークとして、手動で設定します" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Remove this repository" +"Force locking on repository. Works only when anonymous access is " +"disabled. Trigering a pull locks repository by user who pulled, only the " +"same user can unlock by doing a push" +msgstr "リポジトリのロックを強制します。匿名アクセスが無効のときしか使えません。ユーザーがリポジトリをプルすると、そのユーザーでリポジトリをロックし、同じユーザーがプッシュするまでアンロックしません。" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "このリポジトリを削除してもよろしいですか? : %s" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +msgid "Delete this repository" msgstr "このリポジトリを削除" -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Confirm to delete this repository" -msgstr "このリポジトリを削除しますか?" - -#: rhodecode/templates/admin/repos/repo_edit.html:310 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 #, python-format msgid "this repository has %s fork" msgid_plural "this repository has %s forks" msgstr[0] "%s 個のフォークがあります" -#: rhodecode/templates/admin/repos/repo_edit.html:311 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 msgid "Detach forks" msgstr "フォークの切り離し" -#: rhodecode/templates/admin/repos/repo_edit.html:312 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 msgid "Delete forks" msgstr "フォークも削除" -#: rhodecode/templates/admin/repos/repo_edit.html:315 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "" +"This repository will be renamed in a special way in order to be " +"unaccesible for Kallithea and VCS systems. If you need to fully delete it" +" from file system please do it manually" +msgstr "" +"このリポジトリはKallitheaとVCSシステムからアクセス出来ないようにするために特別な方法でリネームされます。\n" +"完全な削除が必要な場合はファイルシステムから手動で削除してください" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "リポジトリのキャッシュを無効化" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "リポジトリのキャッシュを無効化してもよろしいですか?" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 msgid "" -"This repository will be renamed in a special way in order to be unaccesible " -"for RhodeCode and VCS systems. If you need to fully delete it from file " -"system please do it manually" -msgstr "このリポジトリはRhodeCodeとVCSシステムからアクセス出来ないようにするために特別な方法でリネームされます。\n完全な削除が必要な場合はファイルシステムから手動で削除してください" - -#: rhodecode/templates/admin/repos/repo_edit.html:329 -msgid "Extra fields" -msgstr "拡張フィールド" - -#: rhodecode/templates/admin/repos/repo_edit.html:341 +"Manually invalidate cache for this repository. On first access repository" +" will be cached again" +msgstr "このリポジトリのキャッシュを手動で無効化します。リポジトリへの初回アクセス時に再びキャッシュされます。" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "キャッシュしている値の一覧" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "プレフィックス" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "キー" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "アクティブ" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "ラベル" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 #, python-format msgid "Confirm to delete this field: %s" -msgstr "このフィールドを削除してよろしいですか: %s" - -#: rhodecode/templates/admin/repos/repo_edit.html:355 +msgstr "このフィールドを削除してもよろしいですか? : %s" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 msgid "New field key" msgstr "新しいフィールドのキー" -#: rhodecode/templates/admin/repos/repo_edit.html:363 +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 msgid "New field label" msgstr "新しいフィールドのラベル" -#: rhodecode/templates/admin/repos/repo_edit.html:366 +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 msgid "Enter short label" msgstr "ラベルを入力してください" -#: rhodecode/templates/admin/repos/repo_edit.html:372 +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 msgid "New field description" msgstr "新しいフィールドの説明" -#: rhodecode/templates/admin/repos/repo_edit.html:375 +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 msgid "Enter description of a field" msgstr "フィールドの説明を入力してください" -#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:3 -msgid "none" -msgstr "なし" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:4 -msgid "read" -msgstr "読込" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:5 -msgid "write" -msgstr "書込" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:6 -msgid "admin" -msgstr "管理" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:7 -msgid "member" -msgstr "メンバー" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "拡張フィールドは無効化されています" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 msgid "private repository" msgstr "非公開リポジトリ" -#: rhodecode/templates/admin/repos/repo_edit_perms.html:19 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:28 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:20 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:35 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:20 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:35 -msgid "default" -msgstr "default" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:33 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:58 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:25 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:55 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:25 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:55 -msgid "revoke" -msgstr "取消" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:83 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:81 -msgid "Add another member" -msgstr "別のメンバーを追加" - -#: rhodecode/templates/admin/repos/repos.html:5 +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "リモート URL" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "リモートから変更を取り込む" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "リモートから変更を取り込んでもよろしいですか?" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "このリポジトリにリモート URLは設定されていません" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "変更不能ID" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "これは何?" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "id を使ってURLを表現" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 +msgid "" +"In case this repository is renamed or moved into another group the " +"repository url changes.\n" +" Using above url guarantees that this " +"repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases" +" that you need to hardcode the url into 3rd party service." +msgstr "" +"通常、リポジトリの名前を変更したり、別のグループに移動すると、リポジトリのURLが変わります。\n" +"上のURLを使えば、常にリポジトリにアクセスできます。\n" +"この機能は、CIを使っている場合や、3rd pirtyのサービス向けにURLをハードコードしたいときに便利です。" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "クローンURI" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "編集" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "オプション:このリポジトリが属するグループを選択します" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "ファイルページ、ダウンロード、検索、READMEのデフォルトのリビジョンを指定します" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "リポジトリの所有者を変更" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "処理済みコミット数" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "処理状況" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "統計情報をリセット" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "現在の統計情報をリセットしてもよろしいですか?" + +#: kallithea/templates/admin/repos/repos.html:5 msgid "Repositories administration" msgstr "リポジトリ管理" -#: rhodecode/templates/admin/repos/repos.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account.html:185 -#: rhodecode/templates/admin/users/users.html:109 -#: rhodecode/templates/bookmarks/bookmarks.html:76 -#: rhodecode/templates/branches/branches.html:75 -#: rhodecode/templates/journal/journal.html:206 -#: rhodecode/templates/journal/journal.html:296 -#: rhodecode/templates/tags/tags.html:76 -msgid "No records found." -msgstr "レコードが見つかりません" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:87 -msgid "apply to children" -msgstr "子リポジトリにも適用" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:88 -msgid "" -"Set or revoke permission to all children of that group, including non-" -"private repositories and other groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:4 -#, python-format -msgid "%s Group Dashboard" -msgstr "%s グループダッシュボード" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:9 -msgid "Home" -msgstr "ホーム" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:13 -msgid "with" -msgstr "と" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5 -msgid "Add repository group" -msgstr "リポジトリグループを追加" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:16 -#: rhodecode/templates/base/base.html:75 rhodecode/templates/base/base.html:91 -msgid "Repository groups" -msgstr "リポジトリグループ" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:13 -msgid "Add new repository group" -msgstr "新しいリポジトリグループを追加" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:51 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:56 -msgid "Group parent" -msgstr "親グループ" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:59 -msgid "save" -msgstr "保存" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5 -msgid "Edit repository group" -msgstr "リポジトリグループを編集" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:13 -#, python-format -msgid "Edit repository group %s" -msgstr "リポジトリグループを編集 %s" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:27 -msgid "Add child group" -msgstr "子グループを追加" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:68 -msgid "" -"Enable lock-by-pulling on group. This option will be applied to all other " -"groups and repositories inside" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5 -msgid "Repository groups administration" -msgstr "リポジトリグループ管理" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:45 -msgid "Number of toplevel repositories" -msgstr "トップレベルリポジトリの数" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:64 -#: rhodecode/templates/admin/users_groups/users_groups.html:48 -#: rhodecode/templates/changeset/changeset_file_comment.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:171 -msgid "Edit" -msgstr "編集" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:65 -#: rhodecode/templates/admin/users_groups/users_groups.html:49 -#: rhodecode/templates/base/perms_summary.html:29 -#: rhodecode/templates/base/perms_summary.html:60 -#: rhodecode/templates/base/perms_summary.html:62 -#: rhodecode/templates/data_table/_dt_elements.html:116 -#: rhodecode/templates/data_table/_dt_elements.html:117 -#: rhodecode/templates/data_table/_dt_elements.html:130 -#: rhodecode/templates/data_table/_dt_elements.html:131 -msgid "edit" -msgstr "編集" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#, python-format -msgid "Confirm to delete this group: %s with %s repository" -msgid_plural "Confirm to delete this group: %s with %s repositories" -msgstr[0] "このグループを削除してもよろしいですか?: %s %s リポジトリ" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:78 -msgid "There are no repository groups yet" -msgstr "まだリポジトリグループがありません" - -#: rhodecode/templates/admin/settings/hooks.html:5 -#: rhodecode/templates/admin/settings/settings.html:5 +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "状態" + +#: kallithea/templates/admin/settings/settings.html:5 msgid "Settings administration" msgstr "設定管理" -#: rhodecode/templates/admin/settings/hooks.html:24 -msgid "Built in hooks - read only" -msgstr "組み込みフック - 読み込み専用" - -#: rhodecode/templates/admin/settings/hooks.html:40 +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "VCS" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "再マップと再スキャン" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "表示" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "フック" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "全文検索" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "システム情報" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "メールアドレスプレフィックス" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "Kallithea メールのFrom" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "エラーメールのFrom" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "エラーメールの宛先" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "SMTP サーバー" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "SMTP ユーザー名" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "SMTP パスワード" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "SMTP ポート" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "SMTP TLSの使用" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "SMTP SSLの使用" + +#: kallithea/templates/admin/settings/settings_email.html:16 +msgid "SMTP auth" +msgstr "SMTP 認証" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "テストメールの送信" + +#: kallithea/templates/admin/settings/settings_email.html:39 +msgid "Send" +msgstr "送信" + +#: kallithea/templates/admin/settings/settings_global.html:8 +msgid "Site branding" +msgstr "サイト名" + +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "このKallitheaサービスのカスタムタイトルを設定します。" + +#: kallithea/templates/admin/settings/settings_global.html:18 +msgid "HTTP authentication realm" +msgstr "HTTP認証レルム" + +#: kallithea/templates/admin/settings/settings_global.html:27 +msgid "Google Analytics code" +msgstr "Google Analyticsコード" + +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "ReCaptcha 公開鍵" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "reCaptchaの公開鍵。" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "ReCaptcha 秘密鍵" + +#: kallithea/templates/admin/settings/settings_global.html:50 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration" +msgstr "reCaptchaの秘密鍵。この値が設定されると登録時のキャプチャが有効になります。" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 +msgid "Save settings" +msgstr "設定を保存" + +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "組み込みのMercurialフック - 編集不可" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "" +"Hooks can be used to trigger actions on certain events such as push / " +"pull. They can trigger Python functions or external applications." +msgstr "フックを使うと、リポジトリへのプッシュやプルといった特定のイベントに合わせて、何らかのアクションを実行できます。フック機能では、Pythonの関数を呼び出したり、外部アプリケーションを起動したりできます。" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 msgid "Custom hooks" msgstr "カスタムフック" -#: rhodecode/templates/admin/settings/hooks.html:56 -msgid "remove" -msgstr "削除" - -#: rhodecode/templates/admin/settings/hooks.html:88 +#: kallithea/templates/admin/settings/settings_hooks.html:69 msgid "Failed to remove hook" msgstr "フックの削除に失敗しました" -#: rhodecode/templates/admin/settings/settings.html:26 -msgid "Remap and rescan repositories" -msgstr "リポジトリの再マッピングと再スキャン" - -#: rhodecode/templates/admin/settings/settings.html:34 +#: kallithea/templates/admin/settings/settings_mapping.html:6 msgid "Rescan option" msgstr "再スキャンオプション" -#: rhodecode/templates/admin/settings/settings.html:40 -msgid "" -"In case a repository was deleted from filesystem and there are leftovers in " -"the database check this option to scan obsolete data in database and remove " -"it." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:41 +#: kallithea/templates/admin/settings/settings_mapping.html:11 msgid "Destroy old data" msgstr "古いデータを削除する" -#: rhodecode/templates/admin/settings/settings.html:43 +#: kallithea/templates/admin/settings/settings_mapping.html:13 +msgid "" +"In case a repository was deleted from filesystem and it still exists in " +"the database check this option to scan obsolete data in database and " +"remove it." +msgstr "リポジトリがファイルシステム上からなくなったのに、データベース上には残っている場合、このオプションを選んで、データベースから古いデータベースを検出し、削除してください。" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "すべてのリポジトリのキャッシュを無効化する" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 msgid "" -"Rescan repositories location for new repositories. Also deletes obsolete if " -"`destroy` flag is checked " -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:48 -msgid "Rescan repositories" -msgstr "リポジトリを再チェック" - -#: rhodecode/templates/admin/settings/settings.html:54 -msgid "Whoosh indexing" -msgstr "Whooshインデックス" - -#: rhodecode/templates/admin/settings/settings.html:62 +"Each cache data for repositories will be cleaned with this option " +"selected. Use this to reload data and clear cache keys." +msgstr "このオプションを選ぶと、各リポジトリのキャッシュデータを抹消します。データのリロードやキャッシュキーの消去が必要なときに使ってください。" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "GITフックをインストール" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 +msgid "" +"Verify if Kallitheas GIT hooks are installed for each repository. Current" +" hooks will be updated to latest version" +msgstr "各リポジトリに Kallitheas の GIT フックがインストールされているか確認してください。現在のフックは最新版に更新されます" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "リポジトリを再スキャン" + +#: kallithea/templates/admin/settings/settings_search.html:7 msgid "Index build option" msgstr "インデックス作成時の設定" -#: rhodecode/templates/admin/settings/settings.html:67 +#: kallithea/templates/admin/settings/settings_search.html:12 msgid "Build from scratch" msgstr "一度削除してから再度インデックスを作成" -#: rhodecode/templates/admin/settings/settings.html:73 +#: kallithea/templates/admin/settings/settings_search.html:15 +msgid "" +"This option completely reindex all the files within Kallithea for proper " +"fulltext search capabilities." +msgstr "このオプションを使うと、全文検索の機能が正しく発揮されるよう、 Kallithea 中の全てのファイルのインデックスを再生成します。" + +#: kallithea/templates/admin/settings/settings_search.html:21 msgid "Reindex" msgstr "再インデックス" -#: rhodecode/templates/admin/settings/settings.html:79 -msgid "Global application settings" -msgstr "アプリケーション全体の設定" - -#: rhodecode/templates/admin/settings/settings.html:88 -msgid "Site branding" -msgstr "サイト名" - -#: rhodecode/templates/admin/settings/settings.html:97 -msgid "HTTP authentication realm" -msgstr "HTTP認証レルム" - -#: rhodecode/templates/admin/settings/settings.html:106 -msgid "Google Analytics code" -msgstr "Google Analyticsコード" - -#: rhodecode/templates/admin/settings/settings.html:114 -#: rhodecode/templates/admin/settings/settings.html:195 -#: rhodecode/templates/admin/settings/settings.html:287 -msgid "Save settings" -msgstr "設定を保存" - -#: rhodecode/templates/admin/settings/settings.html:121 -msgid "Visualisation settings" -msgstr "表示の設定" - -#: rhodecode/templates/admin/settings/settings.html:129 +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "Kallithea バージョン" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "更新を確認" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "Python バージョン" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "プラットフォーム" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "GIT バージョン" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "GIT パス" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "更新情報のエンドポイント" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "ノート: サーバーがこのURLにアクセスできることを確認して下さい" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "更新を確認中..." + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "Python パッケージ" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 +msgid "Web" +msgstr "Web" + +#: kallithea/templates/admin/settings/settings_vcs.html:11 +msgid "Require SSL for vcs operations" +msgstr "VCSの操作にSSLを必須とする" + +#: kallithea/templates/admin/settings/settings_vcs.html:13 +msgid "" +"Activate to set Kallithea to require SSL for pushing or pulling. If SSL " +"certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "プッシュ、プル時にSSLを要求します。SSLでない場合はHTTP Error 406: Not Acceptableを返します。" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 +msgid "Show repository size after push" +msgstr "プッシュ後にリポジトリのサイズを表示する" + +#: kallithea/templates/admin/settings/settings_vcs.html:28 +msgid "Log user push commands" +msgstr "ユーザーのプッシュコマンドを記録する" + +#: kallithea/templates/admin/settings/settings_vcs.html:32 +msgid "Log user pull commands" +msgstr "ユーザーのプルコマンドを記録する" + +#: kallithea/templates/admin/settings/settings_vcs.html:36 +msgid "Update repository after push (hg update)" +msgstr "プッシュ後にリポジトリを更新する (hg update)" + +#: kallithea/templates/admin/settings/settings_vcs.html:42 +msgid "Mercurial Extensions" +msgstr "Mercurialエクステンション" + +#: kallithea/templates/admin/settings/settings_vcs.html:47 +msgid "Enable largefiles extension" +msgstr "largefilesエクステンションを有効にする" + +#: kallithea/templates/admin/settings/settings_vcs.html:51 +msgid "Enable hgsubversion extension" +msgstr "hgsubversionエクステンションを有効にする" + +#: kallithea/templates/admin/settings/settings_vcs.html:53 +msgid "" +"Requires hgsubversion library to be installed. Allows cloning remote SVN " +"repositories and migrates them to Mercurial type." +msgstr "" +"hgsubversion " +"ライブラリのインストールが必要です。リモートのSVNリポジトリをクローンしてMercurialリポジトリに変換するすることが可能です。" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 +msgid "Repositories location" +msgstr "リポジトリロケーション" + +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting" +" take effect." +msgstr "アンロックする。この設定を有効にするためにはKallitheaの再起動が必要です。" + +#: kallithea/templates/admin/settings/settings_vcs.html:72 +msgid "" +"Filesystem location where repositories should be stored. After changing " +"this value a restart and rescan of the repository folder are required." +msgstr "リポジトリを保存するファイルシステムのロケーション。この値を変更した場合、サーバーの再起動とリポジトリフォルダの再スキャンが必要です。" + +#: kallithea/templates/admin/settings/settings_visual.html:8 msgid "General" msgstr "一般" -#: rhodecode/templates/admin/settings/settings.html:134 +#: kallithea/templates/admin/settings/settings_visual.html:13 msgid "Use repository extra fields" -msgstr "リポジトリの拡張フィールドを使用" - -#: rhodecode/templates/admin/settings/settings.html:136 +msgstr "リポジトリの拡張フィールドを使用する" + +#: kallithea/templates/admin/settings/settings_visual.html:15 msgid "Allows storing additional customized fields per repository." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:139 -msgid "Show RhodeCode version" +msgstr "追加のカスタムフィールドをリポジトリ毎に保存することを許可します。" + +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "Kallitheaのバージョンを表示する" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "フッターに表示されるKallitheaのバージョン番号の表示、非表示を設定します。" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "Gravatorsを利用する" + +#: kallithea/templates/admin/settings/settings_visual.html:30 +msgid "" +"Gravatar url allows you to use other avatar server application.\n" +" Following " +"variables of the URL will be replaced accordingly.\n" +" {scheme} " +"'http' or 'https' sent from running Kallithea server,\n" +" {email} user " +"email,\n" +" {md5email} md5 " +"hash of the user email (like at gravatar.com),\n" +" {size} size " +"of the image that is expected from the server application,\n" +" {netloc} " +"network location/server host of running Kallithea server" msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:141 -msgid "Shows or hides displayed version of RhodeCode in the footer" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:146 -msgid "Dashboard items" +"Gravatar URL を設定すると、外部のアバターサーバーアプリケーションを使用します。\n" +"必要に応じて、 URL に以下の変数を使ってください。\n" +"{scheme} Kallithea サーバからリクエストを送信するときに使うスキーム。 'http' または 'https'\n" +"{email} ユーザーのメールアドレス\n" +"{md5email} ユーザーのメールアドレスの md5 ハッシュ値 (gravatar.com で使っています)\n" +"{size} サーバーアプリケーションに要求する画像のサイズ\n" +"{netloc} Kallithea サーバーのアドレスまたはホスト名" + +#: kallithea/templates/admin/settings/settings_visual.html:42 +msgid "" +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}'," +" available vars:\n" +" {scheme} 'http' " +"or 'https' sent from running Kallithea server,\n" +" {user} current " +"user username,\n" +" {netloc} network " +"location/server host of running Kallithea server,\n" +" {repo} full " +"repository name,\n" +" {repoid} ID of " +"repository, can be used to contruct clone-by-id" msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:150 +"クローン URL のスキーマは、 '{scheme}://{user}@{netloc}/{repo}' " +"のような形式にします。使える変数は下記の通りです:\n" +" {scheme} " +"Kallithea サーバからリクエストを送信するときに使うスキーム。 'http' または 'https'\n" +" {user} " +"ユーザーのユーザー名\n" +" {netloc} " +"Kallithea サーバーのアドレスまたはホスト名\n" +" {repo} " +"リポジトリの完全な名前\n" +" {repoid} リポジトリの " +"ID。 clone-by-id に使います。" + +#: kallithea/templates/admin/settings/settings_visual.html:54 +msgid "Dashboard items" +msgstr "ダッシュボードの項目" + +#: kallithea/templates/admin/settings/settings_visual.html:58 msgid "" -"Number of items displayed in lightweight dashboard before pagination is " +"Number of items displayed in the main page dashboard before pagination is" +" shown." +msgstr "メインページダッシュボードで1ページに表示する要素数。" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "管理ページの項目" + +#: kallithea/templates/admin/settings/settings_visual.html:68 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " "shown." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:155 +msgstr "管理ページで、ページ分割しないでグリッドに表示する項目の数" + +#: kallithea/templates/admin/settings/settings_visual.html:74 msgid "Icons" msgstr "アイコン" -#: rhodecode/templates/admin/settings/settings.html:160 +#: kallithea/templates/admin/settings/settings_visual.html:79 msgid "Show public repo icon on repositories" -msgstr "公開リポジトリのアイコンを表示" - -#: rhodecode/templates/admin/settings/settings.html:164 +msgstr "公開リポジトリのアイコンを表示する" + +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Show private repo icon on repositories" -msgstr "非公開リポジトリのアイコンを表示" - -#: rhodecode/templates/admin/settings/settings.html:166 -msgid "Show public/private icons next to repositories names" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:172 +msgstr "非公開リポジトリのアイコンを表示する" + +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "リポジトリ名の横に公開/非公開アイコンを表示します。" + +#: kallithea/templates/admin/settings/settings_visual.html:91 msgid "Meta-Tagging" msgstr "メタタグ" -#: rhodecode/templates/admin/settings/settings.html:177 -msgid "Stylify recognised metatags:" +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" msgstr "次のメタタグを変換する" -#: rhodecode/templates/admin/settings/settings.html:204 -msgid "VCS settings" -msgstr "VCSの設定" - -#: rhodecode/templates/admin/settings/settings.html:213 -msgid "Web" -msgstr "Web" - -#: rhodecode/templates/admin/settings/settings.html:218 -msgid "Require SSL for vcs operations" -msgstr "VCSの操作にSSLを必須とする" - -#: rhodecode/templates/admin/settings/settings.html:220 +#: kallithea/templates/admin/settings/settings_visual.html:110 msgid "" -"RhodeCode will require SSL for pushing or pulling. If SSL is missing it will" -" return HTTP Error 406: Not Acceptable" -msgstr "RhodeCodeはPushとPullにSSLを要求します。もしSSLでない場合、HTTP Error 406: Not Acceptalbeを返します" - -#: rhodecode/templates/admin/settings/settings.html:226 -msgid "Hooks" -msgstr "フック" - -#: rhodecode/templates/admin/settings/settings.html:231 -msgid "Update repository after push (hg update)" -msgstr "プッシュ後にリポジトリをを更新する (hg update)" - -#: rhodecode/templates/admin/settings/settings.html:235 -msgid "Show repository size after push" -msgstr "プッシュ後にリポジトリのサイズを表示する" - -#: rhodecode/templates/admin/settings/settings.html:239 -msgid "Log user push commands" -msgstr "ユーザーのプッシュコマンドを記録する" - -#: rhodecode/templates/admin/settings/settings.html:243 -msgid "Log user pull commands" -msgstr "ユーザーのプルコマンドを記録する" - -#: rhodecode/templates/admin/settings/settings.html:247 -msgid "Advanced setup" -msgstr "高度な設定" - -#: rhodecode/templates/admin/settings/settings.html:252 -msgid "Mercurial Extensions" -msgstr "Mercurialエクステンション" - -#: rhodecode/templates/admin/settings/settings.html:257 -msgid "Enable largefiles extension" -msgstr "largefilesエクステンションを有効化" - -#: rhodecode/templates/admin/settings/settings.html:261 -msgid "Enable hgsubversion extension" -msgstr "hgsubversionエクステンションを有効化" - -#: rhodecode/templates/admin/settings/settings.html:263 -msgid "" -"Requires hgsubversion library installed. Allows cloning from svn remote " -"locations" -msgstr "hgsubversion のインストールが必要です。リモートロケーションのsvnからクローン出来るようになります" - -#: rhodecode/templates/admin/settings/settings.html:274 -msgid "Repositories location" -msgstr "リポジトリロケーション" - -#: rhodecode/templates/admin/settings/settings.html:279 -msgid "" -"Click to unlock. You must restart RhodeCode in order to make this setting " -"take effect." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:280 -#: rhodecode/templates/base/base.html:143 -msgid "Unlock" -msgstr "アンロック" - -#: rhodecode/templates/admin/settings/settings.html:282 -msgid "" -"Location where repositories are stored. After changing this value a restart," -" and rescan is required" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:303 -msgid "Test Email" -msgstr "テストメール" - -#: rhodecode/templates/admin/settings/settings.html:311 -msgid "Email to" -msgstr "送信先" - -#: rhodecode/templates/admin/settings/settings.html:319 -msgid "Send" -msgstr "送る" - -#: rhodecode/templates/admin/settings/settings.html:325 -msgid "System Info and Packages" -msgstr "システム情報とパッケージ" - -#: rhodecode/templates/admin/settings/settings.html:328 -#: rhodecode/templates/changelog/changelog.html:51 -msgid "Show" -msgstr "表示" - -#: rhodecode/templates/admin/users/user_add.html:5 +"Parses meta tags from repository description field and turns them into " +"colored tags." +msgstr "リポジトリの説明のメタタグを解析して色つきのタグに変換します。" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 +msgid "Add user group" +msgstr "ユーザーグループを追加" + +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 +msgid "User groups" +msgstr "ユーザーグループ" + +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "ユーザーグループを追加" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "このユーザーグループの簡潔な説明を書いてください" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 +#, python-format +msgid "%s user group settings" +msgstr "%s ユーザーグループ設定" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "ユーザーグループ" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "デフォルトの権限" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 +msgid "Members" +msgstr "メンバー" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 +#, python-format +msgid "User Group: %s" +msgstr "ユーサーグループ: %s" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 +#, python-format +msgid "Confirm to delete this user group: %s" +msgstr "このユーザーグループを削除してもよろしいですか?: %s" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "このユーザーグループを削除" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "まだメンバーがいません" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "グループメンバーを選ぶ" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "全ての要素を削除" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "有効なメンバー" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "全ての要素を追加" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "ユーザーグループ管理" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "ユーザーグループ" + +#: kallithea/templates/admin/users/user_add.html:5 msgid "Add user" msgstr "ユーザーを追加" -#: rhodecode/templates/admin/users/user_add.html:10 -#: rhodecode/templates/admin/users/user_edit.html:11 -#: rhodecode/templates/base/base.html:76 +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 msgid "Users" msgstr "ユーザー" -#: rhodecode/templates/admin/users/user_add.html:12 -#: rhodecode/templates/admin/users/users.html:23 -msgid "Add new user" -msgstr "新しいユーザーを追加" - -#: rhodecode/templates/admin/users/user_add.html:50 +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "ユーザーを追加" + +#: kallithea/templates/admin/users/user_add.html:53 msgid "Password confirmation" msgstr "パスワード再入力" -#: rhodecode/templates/admin/users/user_edit.html:5 -msgid "Edit user" -msgstr "ユーザーを編集" - -#: rhodecode/templates/admin/users/user_edit.html:13 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 -#, python-format -msgid "Edit %s" -msgstr "編集 %s" - -#: rhodecode/templates/admin/users/user_edit.html:34 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:10 -msgid "Change your avatar at" -msgstr "アイコンを変えられます : " - -#: rhodecode/templates/admin/users/user_edit.html:35 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:11 -msgid "Using" -msgstr "メールアドレス:" - -#: rhodecode/templates/admin/users/user_edit.html:43 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:20 -msgid "API key" -msgstr "APIキー" - -#: rhodecode/templates/admin/users/user_edit.html:50 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:25 -msgid "Current IP" -msgstr "現在のIP" - -#: rhodecode/templates/admin/users/user_edit.html:70 -msgid "LDAP DN" -msgstr "LDAP DN" - -#: rhodecode/templates/admin/users/user_edit.html:79 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:44 -msgid "New password" -msgstr "新しいパスワード" - -#: rhodecode/templates/admin/users/user_edit.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:53 +#: kallithea/templates/admin/users/user_edit.html:5 +#, python-format +msgid "%s user settings" +msgstr "%s ユーザー設定" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "メールアドレス" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "IPアドレスのホワイトリスト" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "ユーザー: %s" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "アカウントのソース" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "最終ログイン日時" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "グループのメンバー数" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "このユーザーを削除してもよろしいですか? : %s" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "このユーザーを削除" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "%s から継承" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "アバターを変更:" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "メールアドレスがありません。このユーザーのメールアドレスを更新してください。" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 +#, python-format +msgid "" +"This user is in an external Source of Record (%s); some details cannot be" +" managed here." +msgstr "このユーザーは外部の Source of Record (%s) に属しています。ここでは詳細を管理できません。" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "アカウントのソースでの名前" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 msgid "New password confirmation" msgstr "新しいパスワード 再入力" -#: rhodecode/templates/admin/users/user_edit.html:163 -msgid "Email addresses" -msgstr "メールアドレス" - -#: rhodecode/templates/admin/users/user_edit.html:176 -#, python-format -msgid "Confirm to delete this email: %s" -msgstr "このメールを削除してよろしいですか: %s" - -#: rhodecode/templates/admin/users/user_edit.html:190 -msgid "New email address" -msgstr "新しいメールアドレス" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:5 -#: rhodecode/templates/base/base.html:254 -msgid "My account" -msgstr "アカウント" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:9 -msgid "My Account" -msgstr "アカウント" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:35 -msgid "My permissions" -msgstr "権限" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:38 -#: rhodecode/templates/journal/journal.html:54 -msgid "My repos" -msgstr "リポジトリ" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:41 -msgid "My pull requests" -msgstr "プルリクエスト" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:4 -msgid "Show closed pull requests" -msgstr "クローズしたプルリクエストを表示" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:6 -msgid "Opened by me" -msgstr "自分が作成" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "プルリクエスト #%s %s に作成" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:17 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:45 -#: rhodecode/templates/pullrequests/pullrequest_data.html:11 -#: rhodecode/templates/pullrequests/pullrequest_show.html:27 -#: rhodecode/templates/pullrequests/pullrequest_show.html:42 -msgid "Closed" -msgstr "クローズ" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:23 -msgid "Confirm to delete this pull request" -msgstr "このプルリクエストを削除しますか?" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:30 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:51 -msgid "Nothing here yet" -msgstr "まだありません" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:34 -msgid "I participate in" -msgstr "レビュアーとして参加" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:42 -#: rhodecode/templates/pullrequests/pullrequest_data.html:8 -#, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "プルリクエスト #%s %s によって %s に作成" - -#: rhodecode/templates/admin/users/users.html:5 +#: kallithea/templates/admin/users/users.html:5 msgid "Users administration" msgstr "ユーザー管理" -#: rhodecode/templates/admin/users/users.html:9 +#: kallithea/templates/admin/users/users.html:13 msgid "users" msgstr "ユーザー" -#: rhodecode/templates/admin/users/users.html:80 +#: kallithea/templates/admin/users/users.html:54 msgid "Firstname" msgstr "名前" -#: rhodecode/templates/admin/users/users.html:81 +#: kallithea/templates/admin/users/users.html:55 msgid "Lastname" msgstr "名字" -#: rhodecode/templates/admin/users/users.html:82 +#: kallithea/templates/admin/users/users.html:56 msgid "Last login" msgstr "最終ログイン日時" -#: rhodecode/templates/admin/users_groups/users_group_add.html:5 -msgid "Add user group" -msgstr "ユーザーグループを追加" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:10 -#: rhodecode/templates/admin/users_groups/users_groups.html:11 -#: rhodecode/templates/base/base.html:77 rhodecode/templates/base/base.html:94 -msgid "User groups" -msgstr "ユーザーグループ" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:12 -#: rhodecode/templates/admin/users_groups/users_groups.html:26 -msgid "Add new user group" -msgstr "新しいユーザーグループを追加" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 -msgid "Edit user group" -msgstr "ユーザーグループを編集" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 -msgid "UserGroups" -msgstr "ユーザーグループ" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 -#: rhodecode/templates/admin/users_groups/users_groups.html:38 -msgid "Members" -msgstr "メンバー" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 -msgid "Chosen group members" -msgstr "グループメンバーを選ぶ" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 -msgid "Remove all elements" -msgstr "全ての要素を削除" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 -msgid "Available members" -msgstr "有効なメンバー" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 -msgid "Add all elements" -msgstr "全ての要素を追加" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:109 -msgid "No members yet" -msgstr "まだメンバーがいません" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:117 -msgid "Global Permissions" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:5 -msgid "User groups administration" -msgstr "ユーザーグループ管理" - -#: rhodecode/templates/admin/users_groups/users_groups.html:55 -#, python-format -msgid "Confirm to delete this user group: %s" -msgstr "ユーザグループを削除しますか?: %s" - -#: rhodecode/templates/admin/users_groups/users_groups.html:62 -msgid "There are no user groups yet" -msgstr "" - -#: rhodecode/templates/base/base.html:42 +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "認証タイプ" + +#: kallithea/templates/base/base.html:37 #, python-format msgid "Server instance: %s" -msgstr "" - -#: rhodecode/templates/base/base.html:52 -msgid "Report a bug" -msgstr "" - -#: rhodecode/templates/base/base.html:121 -#: rhodecode/templates/data_table/_dt_elements.html:9 -#: rhodecode/templates/data_table/_dt_elements.html:11 -#: rhodecode/templates/data_table/_dt_elements.html:13 -#: rhodecode/templates/summary/summary.html:8 +msgstr "サーバーインスタンス: %s" + +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "サポート" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "フォークを作成" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 msgid "Summary" msgstr "要約" -#: rhodecode/templates/base/base.html:122 -#: rhodecode/templates/changelog/changelog.html:15 -#: rhodecode/templates/data_table/_dt_elements.html:17 -#: rhodecode/templates/data_table/_dt_elements.html:19 -#: rhodecode/templates/data_table/_dt_elements.html:21 +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 msgid "Changelog" msgstr "履歴" -#: rhodecode/templates/base/base.html:123 -#: rhodecode/templates/data_table/_dt_elements.html:25 -#: rhodecode/templates/data_table/_dt_elements.html:27 -#: rhodecode/templates/data_table/_dt_elements.html:29 -#: rhodecode/templates/files/files.html:12 +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 msgid "Files" msgstr "ファイル" -#: rhodecode/templates/base/base.html:125 +#: kallithea/templates/base/base.html:149 msgid "Switch To" msgstr "ブランチの切り替え" -#: rhodecode/templates/base/base.html:127 -#: rhodecode/templates/base/base.html:279 -msgid "loading..." -msgstr "読み込み中..." - -#: rhodecode/templates/base/base.html:131 +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 msgid "Options" msgstr "オプション" -#: rhodecode/templates/base/base.html:137 -#: rhodecode/templates/forks/forks_data.html:21 +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 msgid "Compare fork" msgstr "フォークを比較" -#: rhodecode/templates/base/base.html:139 -#: rhodecode/templates/base/base.html:312 -#: rhodecode/templates/search/search.html:14 -#: rhodecode/templates/search/search.html:54 +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "比較" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 msgid "Search" msgstr "検索" -#: rhodecode/templates/base/base.html:145 +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "アンロック" + +#: kallithea/templates/base/base.html:176 msgid "Lock" msgstr "ロック" -#: rhodecode/templates/base/base.html:153 +#: kallithea/templates/base/base.html:184 msgid "Follow" msgstr "フォロー" -#: rhodecode/templates/base/base.html:154 +#: kallithea/templates/base/base.html:185 msgid "Unfollow" msgstr "アンフォロー" -#: rhodecode/templates/base/base.html:157 -#: rhodecode/templates/data_table/_dt_elements.html:33 -#: rhodecode/templates/data_table/_dt_elements.html:35 -#: rhodecode/templates/data_table/_dt_elements.html:37 -#: rhodecode/templates/data_table/_dt_elements.html:74 -#: rhodecode/templates/forks/fork.html:9 +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 msgid "Fork" msgstr "フォーク" -#: rhodecode/templates/base/base.html:159 +#: kallithea/templates/base/base.html:190 msgid "Create Pull Request" msgstr "プルリクエストを作成" -#: rhodecode/templates/base/base.html:165 -msgid "Show Pull Requests" -msgstr "プルリクエストを表示" - -#: rhodecode/templates/base/base.html:165 -msgid "Pull Requests" -msgstr "プルリクエスト" - -#: rhodecode/templates/base/base.html:202 +#: kallithea/templates/base/base.html:196 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "%s のプルリクエストを表示" + +#: kallithea/templates/base/base.html:233 msgid "Not logged in" msgstr "ログインしていません" -#: rhodecode/templates/base/base.html:209 +#: kallithea/templates/base/base.html:240 msgid "Login to your account" msgstr "ログイン" -#: rhodecode/templates/base/base.html:232 +#: kallithea/templates/base/base.html:263 msgid "Forgot password ?" -msgstr "パスワードを忘れた場合はこちら" - -#: rhodecode/templates/base/base.html:255 +msgstr "パスワードを忘れた?" + +#: kallithea/templates/base/base.html:286 msgid "Log Out" msgstr "ログアウト" -#: rhodecode/templates/base/base.html:274 -msgid "Switch repository" -msgstr "リポジトリの切り替え" - -#: rhodecode/templates/base/base.html:286 +#: kallithea/templates/base/base.html:311 msgid "Show recent activity" msgstr "最近の活動を表示" -#: rhodecode/templates/base/base.html:287 -#: rhodecode/templates/journal/journal.html:4 +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 msgid "Journal" msgstr "ジャーナル" -#: rhodecode/templates/base/base.html:298 +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "公開ジャーナル" + +#: kallithea/templates/base/base.html:323 msgid "Show public gists" -msgstr "" - -#: rhodecode/templates/base/base.html:303 +msgstr "公開 gists を表示" + +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "Gists" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "新しい gist を作成" + +#: kallithea/templates/base/base.html:328 msgid "All public gists" -msgstr "" - -#: rhodecode/templates/base/base.html:305 +msgstr "すべての公開 gists" + +#: kallithea/templates/base/base.html:330 msgid "My public gists" -msgstr "" - -#: rhodecode/templates/base/base.html:306 +msgstr "公開 gists" + +#: kallithea/templates/base/base.html:331 msgid "My private gists" -msgstr "" - -#: rhodecode/templates/base/base.html:311 +msgstr "非公開 gists" + +#: kallithea/templates/base/base.html:336 msgid "Search in repositories" -msgstr "全てのリポジトリから検索" - -#: rhodecode/templates/base/default_perms_box.html:14 -msgid "Inherit default permissions" -msgstr "デフォルトの権限を継承する" - -#: rhodecode/templates/base/default_perms_box.html:18 +msgstr "リポジトリから検索" + +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "一致するものが見つかりません" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "キーボードショートカット" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "サイト全体" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "デフォルト権限を継承" + +#: kallithea/templates/base/default_perms_box.html:19 #, python-format msgid "" -"Select to inherit permissions from %s settings. With this selected below " -"options does not apply." +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:26 +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." + +#: kallithea/templates/base/default_perms_box.html:28 msgid "Create repositories" msgstr "リポジトリを作成する" -#: rhodecode/templates/base/default_perms_box.html:30 +#: kallithea/templates/base/default_perms_box.html:33 msgid "Select this option to allow repository creation for this user" -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:35 +msgstr "ユーザーにリポジトリ作成を許可する場合はこのオプションを選んでください" + +#: kallithea/templates/base/default_perms_box.html:40 msgid "Create user groups" -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:39 +msgstr "ユーザーグループを作成" + +#: kallithea/templates/base/default_perms_box.html:45 msgid "Select this option to allow user group creation for this user" -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:44 +msgstr "ユーザーにユーザーグループの作成を許可する場合はこのオプションを選んでください" + +#: kallithea/templates/base/default_perms_box.html:52 msgid "Fork repositories" msgstr "リポジトリをフォークする" -#: rhodecode/templates/base/default_perms_box.html:48 +#: kallithea/templates/base/default_perms_box.html:57 msgid "Select this option to allow repository forking for this user" +msgstr "ユーザーにリポジトリのフォークを許可する場合はこのオプションを選んでください" + +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" msgstr "" -#: rhodecode/templates/base/perms_summary.html:11 +#: kallithea/templates/base/perms_summary.html:22 msgid "No permissions defined yet" msgstr "まだ権限設定がありません" -#: rhodecode/templates/base/perms_summary.html:19 -#: rhodecode/templates/base/perms_summary.html:38 +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 msgid "Permission" msgstr "権限" -#: rhodecode/templates/base/perms_summary.html:20 -#: rhodecode/templates/base/perms_summary.html:39 +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 msgid "Edit Permission" msgstr "権限を編集" -#: rhodecode/templates/base/root.html:44 +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 msgid "Add another comment" msgstr "別のコメントを追加" -#: rhodecode/templates/base/root.html:45 -#: rhodecode/templates/data_table/_dt_elements.html:147 +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 msgid "Stop following this repository" msgstr "このリポジトリのフォローをやめる" -#: rhodecode/templates/base/root.html:46 +#: kallithea/templates/base/root.html:47 msgid "Start following this repository" msgstr "このリポジトリのフォローする" -#: rhodecode/templates/base/root.html:47 +#: kallithea/templates/base/root.html:48 msgid "Group" msgstr "グループ" -#: rhodecode/templates/base/root.html:48 +#: kallithea/templates/base/root.html:49 msgid "members" msgstr "メンバー" -#: rhodecode/templates/base/root.html:49 -#: rhodecode/templates/pullrequests/pullrequest.html:203 +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 msgid "Loading ..." msgstr "読み込み中..." -#: rhodecode/templates/base/root.html:50 +#: kallithea/templates/base/root.html:51 +msgid "loading ..." +msgstr "読み込み中..." + +#: kallithea/templates/base/root.html:52 msgid "Search truncated" msgstr "検索結果は省略されています" -#: rhodecode/templates/base/root.html:51 +#: kallithea/templates/base/root.html:53 msgid "No matching files" msgstr "マッチするファイルはありません" -#: rhodecode/templates/base/root.html:52 -#: rhodecode/templates/changelog/changelog.html:45 +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 msgid "Open new pull request" msgstr "新しいプルリクエストを作成" -#: rhodecode/templates/base/root.html:53 +#: kallithea/templates/base/root.html:55 msgid "Open new pull request for selected changesets" msgstr "選択したチェンジセットから新しいプルリクエストを作成" -#: rhodecode/templates/base/root.html:54 +#: kallithea/templates/base/root.html:56 msgid "Show selected changesets __S -> __E" msgstr "選択した変更 __S -> __E を表示" -#: rhodecode/templates/base/root.html:55 +#: kallithea/templates/base/root.html:57 msgid "Show selected changeset __S" msgstr "選択した変更 __S を表示" -#: rhodecode/templates/base/root.html:56 +#: kallithea/templates/base/root.html:58 msgid "Selection link" -msgstr "" - -#: rhodecode/templates/base/root.html:57 -#: rhodecode/templates/changeset/diff_block.html:8 +msgstr "セレクション・リンク" + +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 msgid "Collapse diff" -msgstr "差分を折りたたむ" - -#: rhodecode/templates/base/root.html:58 +msgstr "差分をたたむ" + +#: kallithea/templates/base/root.html:60 msgid "Expand diff" msgstr "差分を表示" -#: rhodecode/templates/base/root.html:59 +#: kallithea/templates/base/root.html:61 msgid "Failed to revoke permission" -msgstr "" - -#: rhodecode/templates/bookmarks/bookmarks.html:5 +msgstr "権限の取消に失敗しました" + +#: kallithea/templates/base/root.html:62 +msgid "confirm to revoke permission for {0}: {1} ?" +msgstr "権限 {0}: {1} を取り消してもよろしいですか?" + +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "チェンジセットを指定" + +#: kallithea/templates/bookmarks/bookmarks.html:5 #, python-format msgid "%s Bookmarks" msgstr "%s ブックマーク" -#: rhodecode/templates/bookmarks/bookmarks.html:26 -msgid "Compare bookmarks" -msgstr "" - -#: rhodecode/templates/bookmarks/bookmarks.html:51 -#: rhodecode/templates/bookmarks/bookmarks_data.html:8 -#: rhodecode/templates/branches/branches.html:50 -#: rhodecode/templates/branches/branches_data.html:8 -#: rhodecode/templates/changelog/changelog_summary_data.html:8 -#: rhodecode/templates/tags/tags.html:51 -#: rhodecode/templates/tags/tags_data.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "ブックマークを比較" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 msgid "Author" msgstr "作成者" -#: rhodecode/templates/bookmarks/bookmarks.html:52 -#: rhodecode/templates/bookmarks/bookmarks_data.html:9 -#: rhodecode/templates/branches/branches.html:51 -#: rhodecode/templates/branches/branches_data.html:9 -#: rhodecode/templates/changelog/changelog_summary_data.html:5 -#: rhodecode/templates/tags/tags.html:52 -#: rhodecode/templates/tags/tags_data.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 msgid "Revision" msgstr "リビジョン" -#: rhodecode/templates/bookmarks/bookmarks.html:54 -#: rhodecode/templates/bookmarks/bookmarks_data.html:10 -#: rhodecode/templates/branches/branches.html:53 -#: rhodecode/templates/branches/branches_data.html:10 -#: rhodecode/templates/tags/tags.html:54 -#: rhodecode/templates/tags/tags_data.html:10 -msgid "Compare" -msgstr "比較" - -#: rhodecode/templates/branches/branches.html:5 +#: kallithea/templates/branches/branches.html:5 #, python-format msgid "%s Branches" msgstr "%s ブランチ" -#: rhodecode/templates/branches/branches.html:26 -msgid "Compare branches" -msgstr "ブランチの比較" - -#: rhodecode/templates/changelog/changelog.html:6 +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "ブランチを比較" + +#: kallithea/templates/changelog/changelog.html:6 #, python-format msgid "%s Changelog" msgstr "%s チェンジログ" -#: rhodecode/templates/changelog/changelog.html:19 +#: kallithea/templates/changelog/changelog.html:21 #, python-format msgid "showing %d out of %d revision" msgid_plural "showing %d out of %d revisions" msgstr[0] "%d / %d リビジョンを表示" -#: rhodecode/templates/changelog/changelog.html:39 +#: kallithea/templates/changelog/changelog.html:43 msgid "Clear selection" msgstr "選択を解除" -#: rhodecode/templates/changelog/changelog.html:42 -#: rhodecode/templates/forks/forks_data.html:19 +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 #, python-format msgid "Compare fork with %s" msgstr "%s とフォークを比較" -#: rhodecode/templates/changelog/changelog.html:42 -msgid "Compare fork with parent" -msgstr "フォークを比較" - -#: rhodecode/templates/changelog/changelog.html:78 -#: rhodecode/templates/changelog/changelog_summary_data.html:28 -#, python-format -msgid "Click to open associated pull request #%s" -msgstr "関連するプルリクエストを開く #%s" - -#: rhodecode/templates/changelog/changelog.html:102 -#: rhodecode/templates/summary/summary.html:403 -msgid "Show more" -msgstr "もっと表示" - -#: rhodecode/templates/changelog/changelog.html:115 -#: rhodecode/templates/changelog/changelog_summary_data.html:50 -#: rhodecode/templates/changeset/changeset.html:107 -#: rhodecode/templates/changeset/changeset_range.html:86 +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "フォーク元(%s)とフォークを比較" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "表示" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 +#, python-format +msgid "" +"Changeset status: %s\n" +"Click to open associated pull request #%s" +msgstr "" +"チェンジセットステータス: %s\n" +"関連するプルリクエスト #%s を開く" + +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 +#, python-format +msgid "Changeset status: %s" +msgstr "チェンジセットステータス: %s" + +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "コミットメッセージを展開" + +#: kallithea/templates/changelog/changelog.html:114 +msgid "Changeset has comments" +msgstr "チェンジセットにコメントがあります" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 #, python-format msgid "Bookmark %s" msgstr "ブックマーク %s" -#: rhodecode/templates/changelog/changelog.html:121 -#: rhodecode/templates/changelog/changelog_summary_data.html:56 -#: rhodecode/templates/changeset/changeset.html:113 -#: rhodecode/templates/changeset/changeset_range.html:92 +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 #, python-format msgid "Tag %s" msgstr "タグ %s" -#: rhodecode/templates/changelog/changelog.html:126 -#: rhodecode/templates/changelog/changelog_summary_data.html:61 -#: rhodecode/templates/changeset/changeset.html:117 -#: rhodecode/templates/changeset/changeset_range.html:96 +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 #, python-format msgid "Branch %s" msgstr "ブランチ %s" -#: rhodecode/templates/changelog/changelog.html:286 +#: kallithea/templates/changelog/changelog.html:299 msgid "There are no changes yet" msgstr "まだ変更がありません" -#: rhodecode/templates/changelog/changelog_details.html:4 -#: rhodecode/templates/changeset/changeset.html:91 +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 msgid "Removed" msgstr "削除" -#: rhodecode/templates/changelog/changelog_details.html:5 -#: rhodecode/templates/changeset/changeset.html:92 +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 msgid "Changed" msgstr "変更" -#: rhodecode/templates/changelog/changelog_details.html:6 -#: rhodecode/templates/changeset/changeset.html:93 +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 msgid "Added" msgstr "追加" -#: rhodecode/templates/changelog/changelog_details.html:8 -#: rhodecode/templates/changelog/changelog_details.html:9 -#: rhodecode/templates/changelog/changelog_details.html:10 -#: rhodecode/templates/changeset/changeset.html:95 -#: rhodecode/templates/changeset/changeset.html:96 -#: rhodecode/templates/changeset/changeset.html:97 +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 #, python-format msgid "Affected %s files" msgstr "%s ファイルに影響" -#: rhodecode/templates/changelog/changelog_summary_data.html:6 -#: rhodecode/templates/files/files_add.html:75 -#: rhodecode/templates/files/files_edit.html:61 +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 msgid "Commit message" msgstr "コミットメッセージ" -#: rhodecode/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/changelog/changelog_summary_data.html:7 msgid "Age" msgstr "経過時間" -#: rhodecode/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/changelog/changelog_summary_data.html:9 msgid "Refs" -msgstr "" - -#: rhodecode/templates/changelog/changelog_summary_data.html:86 -msgid "Add or upload files directly via RhodeCode" -msgstr "RhodeCode経由で直接ファイルを追加またはアップロード" - -#: rhodecode/templates/changelog/changelog_summary_data.html:89 -#: rhodecode/templates/files/files_add.html:38 -#: rhodecode/templates/files/files_browser.html:31 -msgid "Add new file" +msgstr "Refs" + +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" +msgstr "Kallithea経由で直接ファイルを追加またはアップロード" + +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" msgstr "新しいファイルを追加" -#: rhodecode/templates/changelog/changelog_summary_data.html:95 +#: kallithea/templates/changelog/changelog_summary_data.html:95 msgid "Push new repo" msgstr "新しいリポジトリをプッシュ" -#: rhodecode/templates/changelog/changelog_summary_data.html:103 +#: kallithea/templates/changelog/changelog_summary_data.html:103 msgid "Existing repository?" msgstr "存在するリポジトリをプッシュ" -#: rhodecode/templates/changeset/changeset.html:6 +#: kallithea/templates/changeset/changeset.html:6 #, python-format msgid "%s Changeset" msgstr "%s チェンジセット" -#: rhodecode/templates/changeset/changeset.html:39 -msgid "No parents" -msgstr "親リビジョンはありません" - -#: rhodecode/templates/changeset/changeset.html:49 -msgid "No children" -msgstr "子リビジョンはありません" - -#: rhodecode/templates/changeset/changeset.html:62 -#: rhodecode/templates/changeset/changeset_file_comment.html:20 -#: rhodecode/templates/changeset/changeset_range.html:44 +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "親リビジョン" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "子リビジョン" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 msgid "Changeset status" -msgstr "リビジョンステータス" - -#: rhodecode/templates/changeset/changeset.html:67 -#: rhodecode/templates/changeset/diff_block.html:22 +msgstr "チェンジセットステータス" + +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 msgid "Raw diff" msgstr "diffとして差分を表示" -#: rhodecode/templates/changeset/changeset.html:68 +#: kallithea/templates/changeset/changeset.html:58 msgid "Patch diff" msgstr "パッチとして差分を表示" -#: rhodecode/templates/changeset/changeset.html:69 -#: rhodecode/templates/changeset/diff_block.html:23 +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 msgid "Download diff" msgstr "差分をダウンロード" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "%d comment" msgid_plural "%d comments" -msgstr[0] "%d コメント" - -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +msgstr[0] "%d 個のコメント" + +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "(%d inline)" msgid_plural "(%d inline)" msgstr[0] "(%d インライン)" -#: rhodecode/templates/changeset/changeset.html:103 -#: rhodecode/templates/changeset/changeset_range.html:82 +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 msgid "merge" msgstr "マージ" -#: rhodecode/templates/changeset/changeset.html:126 -#: rhodecode/templates/compare/compare_diff.html:40 -#: rhodecode/templates/pullrequests/pullrequest_show.html:113 +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 #, python-format msgid "%s file changed" msgid_plural "%s files changed" msgstr[0] "%s ファイルに影響" -#: rhodecode/templates/changeset/changeset.html:128 -#: rhodecode/templates/compare/compare_diff.html:42 -#: rhodecode/templates/pullrequests/pullrequest_show.html:115 +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 #, python-format msgid "%s file changed with %s insertions and %s deletions" msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "%s ファイルに影響。 %s 個の追加と %s 個の削除" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Showing a huge diff might take some time and resources" msgstr "巨大な差分の表示はすこし時間とリソースがかかる場合があります" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Show full diff" msgstr "すべての差分を表示" -#: rhodecode/templates/changeset/changeset_file_comment.html:30 -#, python-format -msgid "Status change on pull request #%s" -msgstr "プルリクエスト #%s のステータスを変更" - -#: rhodecode/templates/changeset/changeset_file_comment.html:32 +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "リビジョンなし" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 +#, python-format +msgid "Vote on pull request #%s" +msgstr "プルリクエスト #%s に投票" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 #, python-format msgid "Comment on pull request #%s" -msgstr "プルリクエストにコメント #%s" - -#: rhodecode/templates/changeset/changeset_file_comment.html:55 +msgstr "プルリクエスト #%s にコメント" + +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Status change on changeset" +msgstr "チェンジセットのステータスを変更" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Comment on changeset" +msgstr "チェンジセットにコメント" + +#: kallithea/templates/changeset/changeset_file_comment.html:63 msgid "Submitting..." -msgstr "サブミット中..." - -#: rhodecode/templates/changeset/changeset_file_comment.html:58 +msgstr "送信中..." + +#: kallithea/templates/changeset/changeset_file_comment.html:66 msgid "Commenting on line {1}." msgstr "{1} 行目にコメント" -#: rhodecode/templates/changeset/changeset_file_comment.html:59 -#: rhodecode/templates/changeset/changeset_file_comment.html:145 +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 #, python-format msgid "Comments parsed using %s syntax with %s support." msgstr "コメントには %s 構文 ( %s サポートつき ) が利用出来ます" -#: rhodecode/templates/changeset/changeset_file_comment.html:61 -#: rhodecode/templates/changeset/changeset_file_comment.html:147 -msgid "" -"Use @username inside this text to send notification to this RhodeCode user" -msgstr "テキスト内で @username を使うと、この RhodeCode のユーザーに通知を送信します" - -#: rhodecode/templates/changeset/changeset_file_comment.html:65 -#: rhodecode/templates/changeset/changeset_file_comment.html:152 +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "テキスト内で @username を使うと、その Kallithea のユーザーに通知を送信します" + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 msgid "Preview" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:72 -#: rhodecode/templates/changeset/changeset_file_comment.html:170 +msgstr "プレビュー" + +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 msgid "Comment preview" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:80 -#: rhodecode/templates/changeset/changeset_file_comment.html:177 -#: rhodecode/templates/email_templates/changeset_comment.html:16 -#: rhodecode/templates/email_templates/pull_request_comment.html:16 +msgstr "コメントのプレビュー" + +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 msgid "Comment" msgstr "コメント" -#: rhodecode/templates/changeset/changeset_file_comment.html:81 -msgid "Cancel" -msgstr "キャンセル" - -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "You need to be logged in to comment." msgstr "コメントするにはログインが必要です" -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "Login now" msgstr "今すぐログインする" -#: rhodecode/templates/changeset/changeset_file_comment.html:92 +#: kallithea/templates/changeset/changeset_file_comment.html:100 msgid "Hide" msgstr "隠す" -#: rhodecode/templates/changeset/changeset_file_comment.html:149 -msgid "Change status" -msgstr "ステータスを変更する" - -#: rhodecode/templates/changeset/changeset_file_comment.html:179 -msgid "Comment and close" -msgstr "コメントしてクローズ" - -#: rhodecode/templates/changeset/changeset_range.html:5 +#: kallithea/templates/changeset/changeset_file_comment.html:159 +msgid "Vote for pull request status" +msgstr "プルリクエストステータスの投票" + +#: kallithea/templates/changeset/changeset_file_comment.html:161 +msgid "Change changeset status" +msgstr "リビジョンステータスを変更" + +#: kallithea/templates/changeset/changeset_file_comment.html:179 +msgid "Close (when approved or rejected)" +msgstr "クローズ(承認もしくは却下した場合)" + +#: kallithea/templates/changeset/changeset_range.html:5 #, python-format msgid "%s Changesets" msgstr "%s チェンジセット" -#: rhodecode/templates/changeset/changeset_range.html:52 +#: kallithea/templates/changeset/changeset_range.html:59 msgid "Files affected" msgstr "影響のあるファイル" -#: rhodecode/templates/changeset/diff_block.html:21 +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 msgid "Show full diff for this file" msgstr "このファイルのすべての差分を表示" -#: rhodecode/templates/changeset/diff_block.html:29 +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Show full side-by-side diff for this file" +msgstr "このファイルの差分を並べて表示" + +#: kallithea/templates/changeset/diff_block.html:38 msgid "Show inline comments" msgstr "インラインコメントを表示" -#: rhodecode/templates/changeset/diff_block.html:53 +#: kallithea/templates/changeset/diff_block.html:62 msgid "Show file at latest version in this repo" msgstr "このリポジトリの最新バージョンのファイルを表示" -#: rhodecode/templates/changeset/diff_block.html:54 +#: kallithea/templates/changeset/diff_block.html:64 msgid "Show file at initial version in this repo" msgstr "このリポジトリの初期バージョンのファイルを表示" -#: rhodecode/templates/compare/compare_cs.html:4 +#: kallithea/templates/compare/compare_cs.html:4 msgid "No changesets" msgstr "チェンジセットはありません" -#: rhodecode/templates/compare/compare_cs.html:32 +#: kallithea/templates/compare/compare_cs.html:8 msgid "Ancestor" msgstr "祖先" -#: rhodecode/templates/compare/compare_diff.html:5 +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 #, python-format msgid "%s Compare" msgstr "%s 比較" -#: rhodecode/templates/compare/compare_diff.html:9 +#: kallithea/templates/compare/compare_diff.html:16 msgid "Compare revisions" -msgstr "リビジョンの比較" - -#: rhodecode/templates/compare/compare_diff.html:33 -#: rhodecode/templates/pullrequests/pullrequest_show.html:106 +msgstr "リビジョンを比較" + +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "入れ替え" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "リビジョンを比較" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "リビジョン、ブランチ、ブックマークもしくはタグの比較を行います。" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 #, python-format msgid "Showing %s commit" msgid_plural "Showing %s commits" msgstr[0] "%s コミットを表示" -#: rhodecode/templates/compare/compare_diff.html:48 -#: rhodecode/templates/pullrequests/pullrequest_show.html:121 +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 msgid "No files" msgstr "ファイルはありません" -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -msgid "confirm to show potentially huge diff" -msgstr "巨大な差分の可能性がありますが表示しますか?" - -#: rhodecode/templates/data_table/_dt_elements.html:54 -#: rhodecode/templates/summary/summary.html:69 +#: kallithea/templates/data_table/_dt_elements.html:63 msgid "Mercurial repository" msgstr "Mercurialリポジトリ" -#: rhodecode/templates/data_table/_dt_elements.html:56 -#: rhodecode/templates/summary/summary.html:72 +#: kallithea/templates/data_table/_dt_elements.html:65 msgid "Git repository" msgstr "Gitリポジトリ" -#: rhodecode/templates/data_table/_dt_elements.html:74 -#, python-format -msgid "Fork of %s" -msgstr "%s のフォーク" - -#: rhodecode/templates/data_table/_dt_elements.html:88 +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "公開リポジトリ" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "リポジトリを作成しています..." + +#: kallithea/templates/data_table/_dt_elements.html:96 msgid "No changesets yet" msgstr "まだチェンジセットがありません" -#: rhodecode/templates/data_table/_dt_elements.html:95 -#: rhodecode/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 #, python-format msgid "Subscribe to %s rss feed" msgstr "%s の RSS フィードを購読" -#: rhodecode/templates/data_table/_dt_elements.html:103 -#: rhodecode/templates/data_table/_dt_elements.html:105 +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 #, python-format msgid "Subscribe to %s atom feed" msgstr "%s の ATOM フィードを購読" -#: rhodecode/templates/data_table/_dt_elements.html:122 -#, python-format -msgid "Confirm to delete this repository: %s" -msgstr "このリポジトリを削除しますか? : %s" - -#: rhodecode/templates/data_table/_dt_elements.html:137 -#, python-format -msgid "Confirm to delete this user: %s" -msgstr "このユーザーを本当に削除してよろしいですか?: %s" - -#: rhodecode/templates/email_templates/changeset_comment.html:4 -#: rhodecode/templates/email_templates/pull_request.html:4 -#: rhodecode/templates/email_templates/pull_request_comment.html:4 -msgid "URL" -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:6 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "作成中" + +#: kallithea/templates/email_templates/changeset_comment.html:6 #, python-format msgid "%s commented on a %s changeset." -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:14 +msgstr "%s が %s のチェンジセットにコメント" + +#: kallithea/templates/email_templates/changeset_comment.html:9 msgid "The changeset status was changed to" -msgstr "" - -#: rhodecode/templates/email_templates/main.html:8 -msgid "This is a notification from RhodeCode." -msgstr "RhodeCodeからの通知です" - -#: rhodecode/templates/email_templates/password_reset.html:4 +msgstr "チェンジセットを次に変更" + +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." +msgstr "Kallitheaからの通知です" + +#: kallithea/templates/email_templates/password_reset.html:4 #, python-format msgid "Hello %s" msgstr "こんにちは %s" -#: rhodecode/templates/email_templates/password_reset.html:5 +#: kallithea/templates/email_templates/password_reset.html:5 msgid "We received a request to create a new password for your account." -msgstr "あなたのアカウントの新しいパスワードの生成リクエストを受け取りました。" - -#: rhodecode/templates/email_templates/password_reset.html:6 +msgstr "アカウントの新しいパスワードの生成リクエストを受け取りました。" + +#: kallithea/templates/email_templates/password_reset.html:6 msgid "You can generate it by clicking following URL" msgstr "下のURLをクリックすることで再生成が行えます。" -#: rhodecode/templates/email_templates/password_reset.html:10 +#: kallithea/templates/email_templates/password_reset.html:10 msgid "Please ignore this email if you did not request a new password ." -msgstr "" - -#: rhodecode/templates/email_templates/pull_request.html:6 +msgstr "新しいパスワードを生成しない場合はこのメールを無視してください。" + +#: kallithea/templates/email_templates/pull_request.html:6 #, python-format msgid "" -"%s opened a pull request for repository %s and wants you to review changes." +"%s opened a pull request for repository %s and wants you to review " +"changes." msgstr "ユーザ %s がリポジトリ %s で新しいプルリクエストを作成しました。変更をレビューしてください。" -#: rhodecode/templates/email_templates/pull_request.html:8 -#: rhodecode/templates/pullrequests/pullrequest.html:34 -#: rhodecode/templates/pullrequests/pullrequest_data.html:14 -#: rhodecode/templates/pullrequests/pullrequest_show.html:25 +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 msgid "Title" msgstr "タイトル" -#: rhodecode/templates/email_templates/pull_request_comment.html:6 +#: kallithea/templates/email_templates/pull_request_comment.html:6 #, python-format msgid "%s commented on pull request \"%s\"" -msgstr "" - -#: rhodecode/templates/email_templates/pull_request_comment.html:10 +msgstr "%s がプルリクエスト\"%s\" にコメントしました" + +#: kallithea/templates/email_templates/pull_request_comment.html:10 msgid "Pull request was closed with status" -msgstr "" - -#: rhodecode/templates/email_templates/pull_request_comment.html:12 +msgstr "プルリクエストを以下のステータスで閉じました:" + +#: kallithea/templates/email_templates/pull_request_comment.html:12 msgid "Pull request changed status" -msgstr "" - -#: rhodecode/templates/email_templates/registration.html:6 +msgstr "プルリクエストを以下のステータスに変更しました:" + +#: kallithea/templates/email_templates/registration.html:6 msgid "View this user here" msgstr "このユーザを閲覧する" -#: rhodecode/templates/errors/error_document.html:55 +#: kallithea/templates/errors/error_document.html:47 #, python-format msgid "You will be redirected to %s in %s seconds" -msgstr "" - -#: rhodecode/templates/files/file_diff.html:4 +msgstr "%s へ %s 秒後にリダイレクトします" + +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "%s ファイルの差分を並べて表示" + +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 +msgid "File diff" +msgstr "ファイル差分" + +#: kallithea/templates/files/diff_2way.html:58 +msgid "ignore white space" +msgstr "空白を無視" + +#: kallithea/templates/files/diff_2way.html:59 +msgid "turn on edit mode" +msgstr "編集モード" + +#: kallithea/templates/files/file_diff.html:4 #, python-format msgid "%s File Diff" msgstr "%s ファイル差分" -#: rhodecode/templates/files/file_diff.html:8 -msgid "File diff" -msgstr "ファイル差分" - -#: rhodecode/templates/files/files.html:4 -#: rhodecode/templates/files/files.html:76 +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 #, python-format msgid "%s Files" msgstr "%s ファイル" -#: rhodecode/templates/files/files.html:30 -#: rhodecode/templates/files/files_add.html:31 -#: rhodecode/templates/files/files_edit.html:31 -msgid "Branch" -msgstr "ブランチ" - -#: rhodecode/templates/files/files_add.html:4 +#: kallithea/templates/files/files_add.html:4 #, python-format msgid "%s Files Add" msgstr "%s ファイルを追加" -#: rhodecode/templates/files/files_add.html:19 -msgid "Add file" -msgstr "ファイルを追加" - -#: rhodecode/templates/files/files_add.html:43 -msgid "File Name" -msgstr "ファイル名" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:56 -msgid "or" -msgstr "または" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:52 -msgid "Upload file" -msgstr "アップロード" - -#: rhodecode/templates/files/files_add.html:56 -msgid "Create new file" -msgstr "新しいファイルを作成" - -#: rhodecode/templates/files/files_add.html:61 -#: rhodecode/templates/files/files_edit.html:37 -#: rhodecode/templates/files/files_ypjax.html:3 +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" +msgstr "新しいファイルを追加" + +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 msgid "Location" msgstr "場所" -#: rhodecode/templates/files/files_add.html:65 -msgid "use / to separate directories" -msgstr "ディレクトリの区切りには / を使います" - -#: rhodecode/templates/files/files_add.html:79 -#: rhodecode/templates/files/files_edit.html:65 +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "ファイル名..." + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 +msgid "or" +msgstr "または" + +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "アップロードファイル" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "新しいファイルを作成" + +#: kallithea/templates/files/files_add.html:58 +msgid "New file mode" +msgstr "ファイルモード" + +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 msgid "Commit changes" msgstr "変更をコミット" -#: rhodecode/templates/files/files_browser.html:13 -msgid "View" -msgstr "閲覧" - -#: rhodecode/templates/files/files_browser.html:14 +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "リビジョン" + +#: kallithea/templates/files/files_browser.html:14 msgid "Previous revision" msgstr "前のリビジョン" -#: rhodecode/templates/files/files_browser.html:16 +#: kallithea/templates/files/files_browser.html:16 msgid "Next revision" msgstr "次のリビジョン" -#: rhodecode/templates/files/files_browser.html:23 +#: kallithea/templates/files/files_browser.html:22 msgid "Follow current branch" msgstr "このブランチで追跡" -#: rhodecode/templates/files/files_browser.html:27 -msgid "Search file list" +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" msgstr "ファイル一覧を検索" -#: rhodecode/templates/files/files_browser.html:35 +#: kallithea/templates/files/files_browser.html:29 msgid "Loading file list..." msgstr "ファイル一覧を読み込み中..." -#: rhodecode/templates/files/files_browser.html:48 +#: kallithea/templates/files/files_browser.html:42 msgid "Size" msgstr "サイズ" -#: rhodecode/templates/files/files_browser.html:49 +#: kallithea/templates/files/files_browser.html:43 msgid "Mimetype" msgstr "Mimetype" -#: rhodecode/templates/files/files_browser.html:50 +#: kallithea/templates/files/files_browser.html:44 msgid "Last Revision" msgstr "最後のリビジョン" -#: rhodecode/templates/files/files_browser.html:51 +#: kallithea/templates/files/files_browser.html:45 msgid "Last modified" msgstr "最終更新日" -#: rhodecode/templates/files/files_browser.html:52 +#: kallithea/templates/files/files_browser.html:46 msgid "Last committer" msgstr "最後の作成者" -#: rhodecode/templates/files/files_edit.html:4 -#, python-format -msgid "%s Files Edit" -msgstr "%s ファイルを編集" - -#: rhodecode/templates/files/files_edit.html:19 +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "%s のファイルを削除" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "ファイルを削除" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "%s のファイルを編集" + +#: kallithea/templates/files/files_edit.html:25 msgid "Edit file" msgstr "ファイルを編集" -#: rhodecode/templates/files/files_edit.html:47 -#: rhodecode/templates/files/files_source.html:23 -msgid "Show annotation" +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" msgstr "アノテーションを表示" -#: rhodecode/templates/files/files_edit.html:49 -#: rhodecode/templates/files/files_source.html:26 -msgid "Download as raw" -msgstr "元のファイルをダウンロード" - -#: rhodecode/templates/files/files_edit.html:52 +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "Raw形式でダウンロード" + +#: kallithea/templates/files/files_edit.html:58 msgid "Source" msgstr "ソース" -#: rhodecode/templates/files/files_edit.html:57 +#: kallithea/templates/files/files_edit.html:63 msgid "Editing file" msgstr "ファイルを編集" -#: rhodecode/templates/files/files_history_box.html:2 -msgid "History" -msgstr "変更履歴" - -#: rhodecode/templates/files/files_history_box.html:9 -msgid "Diff to revision" -msgstr "このリビジョンの差分を見る" - -#: rhodecode/templates/files/files_history_box.html:10 -msgid "Show at revision" -msgstr "このリビジョンを見る" - -#: rhodecode/templates/files/files_history_box.html:11 -msgid "Show full history" -msgstr "すべての履歴を表示" - -#: rhodecode/templates/files/files_history_box.html:16 +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "コミットメッセージ" + +#: kallithea/templates/files/files_history_box.html:2 #, python-format msgid "%s author" msgid_plural "%s authors" -msgstr[0] "%s 作成者" - -#: rhodecode/templates/files/files_source.html:6 -msgid "Load file history" -msgstr "ファイルの履歴を読み込む" - -#: rhodecode/templates/files/files_source.html:21 -msgid "Show source" +msgstr[0] "%s 人の作成者" + +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "このリビジョンとの差分" + +#: kallithea/templates/files/files_source.html:8 +msgid "Show at Revision" +msgstr "このリビジョンを表示" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "全ての履歴を表示" + +#: kallithea/templates/files/files_source.html:11 +msgid "Show Authors" +msgstr "作成者を表示" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" msgstr "ソースを表示" -#: rhodecode/templates/files/files_source.html:29 -#, python-format -msgid "Edit on branch:%s" +#: kallithea/templates/files/files_source.html:38 +#, python-format +msgid "Edit on Branch:%s" msgstr "ブランチ:%s で編集" -#: rhodecode/templates/files/files_source.html:31 -msgid "Edit on branch:?" -msgstr "ブランチ:? で編集" - -#: rhodecode/templates/files/files_source.html:31 +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "バイナリファイルの編集は行えません" + +#: kallithea/templates/files/files_source.html:44 msgid "Editing files allowed only when on branch head revision" msgstr "ファイル編集はブランチのヘッドリビジョンでのみ許可されています" -#: rhodecode/templates/files/files_source.html:46 +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "ファイルの削除はブランチのヘッドリビジョンでのみ行えます" + +#: kallithea/templates/files/files_source.html:61 #, python-format msgid "Binary file (%s)" msgstr "バイナリファイル (%s)" -#: rhodecode/templates/files/files_source.html:55 +#: kallithea/templates/files/files_source.html:71 msgid "File is too big to display" msgstr "表示するには大きすぎるファイルです" -#: rhodecode/templates/files/files_ypjax.html:5 +#: kallithea/templates/files/files_ypjax.html:5 msgid "annotation" msgstr "アノテーション" -#: rhodecode/templates/files/files_ypjax.html:15 -msgid "Go back" +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" msgstr "戻る" -#: rhodecode/templates/files/files_ypjax.html:16 +#: kallithea/templates/files/files_ypjax.html:24 msgid "No files at given path" msgstr "そのパスにはファイルはありません" -#: rhodecode/templates/followers/followers.html:5 +#: kallithea/templates/followers/followers.html:5 #, python-format msgid "%s Followers" msgstr "%s フォロワー" -#: rhodecode/templates/followers/followers.html:9 -#: rhodecode/templates/summary/summary.html:183 -#: rhodecode/templates/summary/summary.html:184 +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 msgid "Followers" msgstr "フォロワー" -#: rhodecode/templates/followers/followers_data.html:12 +#: kallithea/templates/followers/followers_data.html:12 msgid "Started following -" msgstr "フォロー開始日 -" -#: rhodecode/templates/forks/fork.html:5 -#, python-format -msgid "%s Fork" -msgstr "%s フォーク" - -#: rhodecode/templates/forks/fork.html:28 +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "リポジトリ %s をフォーク" + +#: kallithea/templates/forks/fork.html:30 msgid "Fork name" msgstr "フォーク名" -#: rhodecode/templates/forks/fork.html:65 +#: kallithea/templates/forks/fork.html:71 msgid "Private" msgstr "非公開" -#: rhodecode/templates/forks/fork.html:74 +#: kallithea/templates/forks/fork.html:80 msgid "Copy permissions" msgstr "権限のコピー" -#: rhodecode/templates/forks/fork.html:78 +#: kallithea/templates/forks/fork.html:84 msgid "Copy permissions from forked repository" msgstr "フォーク元リポジトリから権限をコピーします" -#: rhodecode/templates/forks/fork.html:84 +#: kallithea/templates/forks/fork.html:90 msgid "Update after clone" msgstr "クローン後にupdateする" -#: rhodecode/templates/forks/fork.html:88 +#: kallithea/templates/forks/fork.html:94 msgid "Checkout source after making a clone" msgstr "クローンした後にソースをチェックアウトします" -#: rhodecode/templates/forks/fork.html:93 -msgid "Fork this repository" +#: kallithea/templates/forks/fork.html:99 +msgid "Fork this Repository" msgstr "このリポジトリをフォーク" -#: rhodecode/templates/forks/forks.html:5 +#: kallithea/templates/forks/forks.html:5 #, python-format msgid "%s Forks" msgstr "%s フォーク" -#: rhodecode/templates/forks/forks.html:9 -#: rhodecode/templates/summary/summary.html:189 -#: rhodecode/templates/summary/summary.html:190 +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 msgid "Forks" msgstr "フォーク" -#: rhodecode/templates/forks/forks_data.html:17 +#: kallithea/templates/forks/forks_data.html:17 msgid "Forked" msgstr "フォークしました" -#: rhodecode/templates/forks/forks_data.html:42 +#: kallithea/templates/forks/forks_data.html:42 msgid "There are no forks yet" msgstr "まだフォークがありません" -#: rhodecode/templates/journal/journal.html:21 +#: kallithea/templates/journal/journal.html:24 msgid "ATOM journal feed" msgstr "ATOM ジャーナルフィード" -#: rhodecode/templates/journal/journal.html:22 +#: kallithea/templates/journal/journal.html:25 msgid "RSS journal feed" msgstr "RSS ジャーナルフィード" -#: rhodecode/templates/journal/journal.html:32 -msgid "Refresh" -msgstr "更新" - -#: rhodecode/templates/journal/journal.html:35 -#: rhodecode/templates/journal/public_journal.html:24 -msgid "ATOM feed" -msgstr "ATOMフィード" - -#: rhodecode/templates/journal/journal.html:51 -msgid "Watched" -msgstr "ウォッチ" - -#: rhodecode/templates/journal/journal_data.html:55 +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "リポジトリ" + +#: kallithea/templates/journal/journal_data.html:55 msgid "No entries yet" msgstr "まだエントリがありません" -#: rhodecode/templates/journal/public_journal.html:4 -#: rhodecode/templates/journal/public_journal.html:21 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 msgid "Public Journal" msgstr "公開ジャーナル" -#: rhodecode/templates/journal/public_journal.html:13 +#: kallithea/templates/journal/public_journal.html:16 msgid "ATOM public journal feed" msgstr "ATOM 公開ジャーナルフィード" -#: rhodecode/templates/journal/public_journal.html:14 +#: kallithea/templates/journal/public_journal.html:17 msgid "RSS public journal feed" msgstr "RSS 公開ジャーナルフィード" -#: rhodecode/templates/pullrequests/pullrequest.html:4 -#: rhodecode/templates/pullrequests/pullrequest.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 msgid "New pull request" msgstr "新しいプルリクエスト" -#: rhodecode/templates/pullrequests/pullrequest.html:25 -msgid "Create new pull request" -msgstr "新しいプルリクエストを作成" - -#: rhodecode/templates/pullrequests/pullrequest.html:47 +#: kallithea/templates/pullrequests/pullrequest.html:44 msgid "Write a short description on this pull request" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.html:53 +msgstr "このプルリクエストの簡潔な説明を書いてください" + +#: kallithea/templates/pullrequests/pullrequest.html:50 msgid "Changeset flow" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.html:60 -#: rhodecode/templates/pullrequests/pullrequest_show.html:65 +msgstr "変更の流れ" + +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 msgid "Origin repository" -msgstr "Originリポジトリ" - -#: rhodecode/templates/pullrequests/pullrequest.html:85 -msgid "Send pull request" -msgstr "プルリクエストを送る" - -#: rhodecode/templates/pullrequests/pullrequest.html:94 -#: rhodecode/templates/pullrequests/pullrequest_show.html:137 +msgstr "元のリポジトリ" + +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "プルリクエストを作成" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 msgid "Pull request reviewers" msgstr "プルリクエストレビュアー" -#: rhodecode/templates/pullrequests/pullrequest.html:103 -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 msgid "owner" msgstr "所有者" -#: rhodecode/templates/pullrequests/pullrequest.html:115 +#: kallithea/templates/pullrequests/pullrequest.html:114 msgid "Add reviewer to this pull request." msgstr "このプルリクエストにレビュアーを追加" -#: rhodecode/templates/pullrequests/pullrequest.html:129 +#: kallithea/templates/pullrequests/pullrequest.html:128 msgid "Detailed compare view" msgstr "比較ビュー詳細" -#: rhodecode/templates/pullrequests/pullrequest.html:150 +#: kallithea/templates/pullrequests/pullrequest.html:149 msgid "Destination repository" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:4 +msgstr "相手のリポジトリ" + +#: kallithea/templates/pullrequests/pullrequest_show.html:4 #, python-format msgid "%s Pull Request #%s" msgstr "%s プルリクエスト #%s" -#: rhodecode/templates/pullrequests/pullrequest_show.html:35 +#: kallithea/templates/pullrequests/pullrequest_show.html:36 msgid "Review status" msgstr "レビューステータス" -#: rhodecode/templates/pullrequests/pullrequest_show.html:40 -msgid "Pull request status" -msgstr "プルリクエストステータス" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 +msgid "Pull request status calculated from votes" +msgstr "投票からプルリクエストのステータスを計算" + +#: kallithea/templates/pullrequests/pullrequest_show.html:56 msgid "Still not reviewed by" msgstr "未レビュー" -#: rhodecode/templates/pullrequests/pullrequest_show.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:60 #, python-format msgid "%d reviewer" msgid_plural "%d reviewers" -msgstr[0] "%d レビュアー" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:59 +msgstr[0] "%d 人のレビュアー" + +#: kallithea/templates/pullrequests/pullrequest_show.html:62 msgid "Pull request was reviewed by all reviewers" msgstr "プルリクエストはすべてのレビュアーにレビューされました" -#: rhodecode/templates/pullrequests/pullrequest_show.html:89 -msgid "Created on" -msgstr "作成日" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:102 +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 +msgid "Pull changes" +msgstr "変更を取得:" + +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "reviewer" +msgstr "レビュアー" + +#: kallithea/templates/pullrequests/pullrequest_show.html:133 +msgid "Add or remove reviewer to this pull request." +msgstr "このプルリクエストにレビュアーを追加/削除" + +#: kallithea/templates/pullrequests/pullrequest_show.html:137 +msgid "Save Changes" +msgstr "変更を保存" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 msgid "Compare view" msgstr "比較ビュー" -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 -msgid "reviewer" -msgstr "レビュアー" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:164 -msgid "Add or remove reviewer to this pull request." -msgstr "このプルリクエストにレビュアーを追加/削除" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:168 -msgid "Save changes" -msgstr "変更を保存" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:4 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 #, python-format msgid "%s Pull Requests" msgstr "%s プルリクエスト" -#: rhodecode/templates/search/search.html:6 -msgid "Search repository" -msgstr "リポジトリから検索" - -#: rhodecode/templates/search/search.html:8 -#: rhodecode/templates/search/search.html:16 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 +#, python-format +msgid "Pull requests from %s" +msgstr "%s からのプルリクエスト" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 +#, python-format +msgid "Pull requests to %s" +msgstr "%s へのプルリクエスト" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "%s へのプルリクエストを表示" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "%s からのプルリクエストを表示" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 +msgid "Hide closed pull requests" +msgstr "クローズしたプルリクエストを隠す" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 +msgid "Show closed pull requests too" +msgstr "クローズしたプルリクエストも表示" + +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "%s 検索" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 msgid "Search in all repositories" msgstr "全てのリポジトリから検索" -#: rhodecode/templates/search/search.html:50 +#: kallithea/templates/search/search.html:53 msgid "Search term" msgstr "検索キーワード" -#: rhodecode/templates/search/search.html:62 +#: kallithea/templates/search/search.html:65 msgid "Search in" msgstr "検索対象" -#: rhodecode/templates/search/search.html:65 +#: kallithea/templates/search/search.html:68 msgid "File contents" -msgstr "ファイル内容" - -#: rhodecode/templates/search/search.html:66 +msgstr "ファイルの内容" + +#: kallithea/templates/search/search.html:69 msgid "Commit messages" msgstr "コミットメッセージ" -#: rhodecode/templates/search/search.html:67 +#: kallithea/templates/search/search.html:70 msgid "File names" msgstr "ファイル名" -#: rhodecode/templates/search/search_commit.html:35 -#: rhodecode/templates/search/search_content.html:21 -#: rhodecode/templates/search/search_path.html:15 +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 msgid "Permission denied" msgstr "権限がありません" -#: rhodecode/templates/summary/summary.html:4 +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "%s 統計情報" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 +#, python-format +msgid "%s ATOM feed" +msgstr "%s ATOM フィード" + +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 +#, python-format +msgid "%s RSS feed" +msgstr "%s RSS フィード" + +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "有効にする" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "収集した統計情報: " + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "ファイル" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "もっと表示" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "コミット" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "追加されたファイル" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "変更されたファイル" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "削除されたファイル" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "コミット" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "追加されたファイル" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "変更されたファイル" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "削除されたファイル" + +#: kallithea/templates/summary/summary.html:4 #, python-format msgid "%s Summary" msgstr "%s 要約" -#: rhodecode/templates/summary/summary.html:16 -#, python-format -msgid "%s ATOM feed" -msgstr "%s ATOM フィード" - -#: rhodecode/templates/summary/summary.html:17 -#, python-format -msgid "%s RSS feed" -msgstr "%s RSS フィード" - -#: rhodecode/templates/summary/summary.html:62 +#: kallithea/templates/summary/summary.html:16 #, python-format msgid "Repository locked by %s" msgstr "リポジトリは %s によってロックされました" -#: rhodecode/templates/summary/summary.html:64 +#: kallithea/templates/summary/summary.html:18 msgid "Repository unlocked" msgstr "リポジトリはロックされていません" -#: rhodecode/templates/summary/summary.html:83 -#, python-format -msgid "Non changable ID %s" -msgstr "変更不能ID %s" - -#: rhodecode/templates/summary/summary.html:88 -msgid "Public" -msgstr "公開" - -#: rhodecode/templates/summary/summary.html:88 -#: rhodecode/templates/summary/summary.html:89 -msgid "Fork of" -msgstr "フォーク元: " - -#: rhodecode/templates/summary/summary.html:97 -msgid "Remote clone" -msgstr "リモートクローン" - -#: rhodecode/templates/summary/summary.html:117 -msgid "Contact" -msgstr "コンタクト" - -#: rhodecode/templates/summary/summary.html:131 +#: kallithea/templates/summary/summary.html:76 msgid "Clone url" msgstr "クローンURL" -#: rhodecode/templates/summary/summary.html:136 +#: kallithea/templates/summary/summary.html:81 msgid "Show by Name" msgstr "名前で表示" -#: rhodecode/templates/summary/summary.html:137 +#: kallithea/templates/summary/summary.html:82 msgid "Show by ID" msgstr "IDで表示" -#: rhodecode/templates/summary/summary.html:143 +#: kallithea/templates/summary/summary.html:99 msgid "Trending files" msgstr "トレンドファイル" -#: rhodecode/templates/summary/summary.html:151 -#: rhodecode/templates/summary/summary.html:167 -msgid "Enable" -msgstr "" - -#: rhodecode/templates/summary/summary.html:159 +#: kallithea/templates/summary/summary.html:115 msgid "Download" msgstr "ダウンロード" -#: rhodecode/templates/summary/summary.html:163 +#: kallithea/templates/summary/summary.html:119 msgid "There are no downloads yet" msgstr "まだダウンロードがありません" -#: rhodecode/templates/summary/summary.html:165 +#: kallithea/templates/summary/summary.html:121 msgid "Downloads are disabled for this repository" msgstr "このリポジトリのダウンロードは無効化されています" -#: rhodecode/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:127 msgid "Download as zip" -msgstr "ZIPとしてダウンロード" - -#: rhodecode/templates/summary/summary.html:174 +msgstr "ZIPでダウンロード" + +#: kallithea/templates/summary/summary.html:132 msgid "Check this to download archive with subrepos" msgstr "チェックするとダウンロードアーカイブにサブリポジトリが含まれます" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "with subrepos" -msgstr "サブリポジトリを含む" - -#: rhodecode/templates/summary/summary.html:197 +msgstr "サブリポジトリを含める" + +#: kallithea/templates/summary/summary.html:163 msgid "Repository Size" msgstr "リポジトリサイズ" -#: rhodecode/templates/summary/summary.html:204 -#: rhodecode/templates/summary/summary.html:206 +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 msgid "Feed" msgstr "フィード" -#: rhodecode/templates/summary/summary.html:224 -msgid "Commit activity by day / author" -msgstr "コミットアクティビティ 日/作成者" - -#: rhodecode/templates/summary/summary.html:232 -msgid "enable" -msgstr "有効にする" - -#: rhodecode/templates/summary/summary.html:235 -msgid "Stats gathered: " -msgstr "収集した統計情報: " - -#: rhodecode/templates/summary/summary.html:256 +#: kallithea/templates/summary/summary.html:193 msgid "Latest changes" msgstr "最近の変更点" -#: rhodecode/templates/summary/summary.html:258 +#: kallithea/templates/summary/summary.html:195 msgid "Quick start" msgstr "クイックスタート" -#: rhodecode/templates/summary/summary.html:272 -#, python-format -msgid "Readme file from revision %s" -msgstr "" - -#: rhodecode/templates/summary/summary.html:332 +#: kallithea/templates/summary/summary.html:209 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "リビジョン %s:%s の README ファイル" + +#: kallithea/templates/summary/summary.html:299 #, python-format msgid "Download %s as %s" -msgstr "%s を %sとしてダウンロード" - -#: rhodecode/templates/summary/summary.html:379 -msgid "files" -msgstr "ファイル" - -#: rhodecode/templates/summary/summary.html:689 -msgid "commits" -msgstr "コミット" - -#: rhodecode/templates/summary/summary.html:690 -msgid "files added" -msgstr "追加されたファイル" - -#: rhodecode/templates/summary/summary.html:691 -msgid "files changed" -msgstr "変更されたファイル" - -#: rhodecode/templates/summary/summary.html:692 -msgid "files removed" -msgstr "削除されたファイル" - -#: rhodecode/templates/summary/summary.html:694 -msgid "commit" -msgstr "コミット" - -#: rhodecode/templates/summary/summary.html:695 -msgid "file added" -msgstr "追加されたファイル" - -#: rhodecode/templates/summary/summary.html:696 -msgid "file changed" -msgstr "変更されたファイル" - -#: rhodecode/templates/summary/summary.html:697 -msgid "file removed" -msgstr "削除されたファイル" - -#: rhodecode/templates/tags/tags.html:5 +msgstr "%s を %s でダウンロード" + +#: kallithea/templates/tags/tags.html:5 #, python-format msgid "%s Tags" msgstr "%s タグ" -#: rhodecode/templates/tags/tags.html:26 +#: kallithea/templates/tags/tags.html:29 msgid "Compare tags" -msgstr "タグの比較" +msgstr "タグを比較" + diff --git a/rhodecode/i18n/rhodecode.pot b/kallithea/i18n/kallithea.pot rename from rhodecode/i18n/rhodecode.pot rename to kallithea/i18n/kallithea.pot --- a/rhodecode/i18n/rhodecode.pot +++ b/kallithea/i18n/kallithea.pot @@ -1,13 +1,13 @@ -# Translations template for RhodeCode. -# Copyright (C) 2013 Marcin Kuzminski RhodeCode -# This file is distributed under the same license as the RhodeCode project. -# FIRST AUTHOR , 2013. +# Translations template for Kallithea. +# Copyright (C) 2014 Various authors, licensing as GPLv3 +# This file is distributed under the same license as the Kallithea project. +# FIRST AUTHOR , 2014. ##, fuzzy msgid "" msgstr "" -"Project-Id-Version: RhodeCode 1.7.1\n" +"Project-Id-Version: Kallithea 2.2.5\n" "Report-Msgid-Bugs-To: marcin@maq.io\n" -"POT-Creation-Date: 2013-07-09 05:02-0700\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,4680 +16,5509 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -#: rhodecode/controllers/changelog.py:88 rhodecode/controllers/compare.py:87 -#: rhodecode/controllers/pullrequests.py:258 +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 msgid "There are no changesets yet" msgstr "" -#: rhodecode/controllers/changelog.py:184 +#: kallithea/controllers/changelog.py:186 msgid "All Branches" msgstr "" -#: rhodecode/controllers/changelog.py:187 +#: kallithea/controllers/changelog.py:189 msgid "(closed)" msgstr "" -#: rhodecode/controllers/changeset.py:84 +#: kallithea/controllers/changeset.py:87 msgid "Show white space" msgstr "" -#: rhodecode/controllers/changeset.py:91 rhodecode/controllers/changeset.py:98 +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 msgid "Ignore white space" msgstr "" -#: rhodecode/controllers/changeset.py:164 -#, python-format -msgid "%s line context" -msgstr "" - -#: rhodecode/controllers/changeset.py:345 -#: rhodecode/controllers/pullrequests.py:474 +#: kallithea/controllers/changeset.py:167 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 #, python-format msgid "Status change -> %s" msgstr "" -#: rhodecode/controllers/changeset.py:376 +#: kallithea/controllers/changeset.py:386 msgid "Changing status on a changeset associated with a closed pull request is not allowed" msgstr "" -#: rhodecode/controllers/error.py:69 +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +msgid "Select changeset" +msgstr "" + +#: kallithea/controllers/error.py:72 msgid "Home page" msgstr "" -#: rhodecode/controllers/error.py:98 +#: kallithea/controllers/error.py:101 msgid "The request could not be understood by the server due to malformed syntax." msgstr "" -#: rhodecode/controllers/error.py:101 +#: kallithea/controllers/error.py:104 msgid "Unauthorized access to resource" msgstr "" -#: rhodecode/controllers/error.py:103 +#: kallithea/controllers/error.py:106 msgid "You don't have permission to view this page" msgstr "" -#: rhodecode/controllers/error.py:105 +#: kallithea/controllers/error.py:108 msgid "The resource could not be found" msgstr "" -#: rhodecode/controllers/error.py:107 +#: kallithea/controllers/error.py:110 msgid "The server encountered an unexpected condition which prevented it from fulfilling the request." msgstr "" -#: rhodecode/controllers/feed.py:52 +#: kallithea/controllers/feed.py:55 #, python-format msgid "Changes on %s repository" msgstr "" -#: rhodecode/controllers/feed.py:53 +#: kallithea/controllers/feed.py:56 #, python-format msgid "%s %s feed" msgstr "" -#: rhodecode/controllers/feed.py:86 -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:138 -#: rhodecode/templates/pullrequests/pullrequest_show.html:202 +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Changeset was too big and was cut off..." msgstr "" -#: rhodecode/controllers/feed.py:90 +#: kallithea/controllers/feed.py:93 #, python-format msgid "%s committed on %s" msgstr "" -#: rhodecode/controllers/files.py:89 +#: kallithea/controllers/files.py:92 msgid "Click here to add new file" msgstr "" -#: rhodecode/controllers/files.py:90 -#, python-format -msgid "There are no files yet %s" -msgstr "" - -#: rhodecode/controllers/files.py:271 rhodecode/controllers/files.py:338 +#: kallithea/controllers/files.py:93 +#, python-format +msgid "There are no files yet. %s" +msgstr "" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 #, python-format msgid "This repository is has been locked by %s on %s" msgstr "" -#: rhodecode/controllers/files.py:283 +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:346 +#, python-format +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "" + +#: kallithea/controllers/files.py:373 msgid "You can only edit files with revision being a valid branch " msgstr "" -#: rhodecode/controllers/files.py:297 -#, python-format -msgid "Edited file %s via RhodeCode" -msgstr "" - -#: rhodecode/controllers/files.py:313 +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:403 msgid "No changes" msgstr "" -#: rhodecode/controllers/files.py:322 rhodecode/controllers/files.py:397 +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 #, python-format msgid "Successfully committed to %s" msgstr "" -#: rhodecode/controllers/files.py:326 rhodecode/controllers/files.py:408 -msgid "Error occurred during commit" -msgstr "" - -#: rhodecode/controllers/files.py:350 -msgid "Added file via RhodeCode" -msgstr "" - -#: rhodecode/controllers/files.py:371 +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:461 msgid "No content" msgstr "" -#: rhodecode/controllers/files.py:375 +#: kallithea/controllers/files.py:465 msgid "No filename" msgstr "" -#: rhodecode/controllers/files.py:400 +#: kallithea/controllers/files.py:490 msgid "Location must be relative path and must not contain .. in path" msgstr "" -#: rhodecode/controllers/files.py:434 +#: kallithea/controllers/files.py:524 msgid "Downloads disabled" msgstr "" -#: rhodecode/controllers/files.py:445 +#: kallithea/controllers/files.py:535 #, python-format msgid "Unknown revision %s" msgstr "" -#: rhodecode/controllers/files.py:447 +#: kallithea/controllers/files.py:537 msgid "Empty repository" msgstr "" -#: rhodecode/controllers/files.py:449 +#: kallithea/controllers/files.py:539 msgid "Unknown archive type" msgstr "" -#: rhodecode/controllers/files.py:705 -#: rhodecode/templates/changeset/changeset_range.html:9 -#: rhodecode/templates/email_templates/pull_request.html:12 -#: rhodecode/templates/pullrequests/pullrequest.html:124 +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 msgid "Changesets" msgstr "" -#: rhodecode/controllers/files.py:706 rhodecode/controllers/pullrequests.py:149 -#: rhodecode/controllers/summary.py:76 rhodecode/model/scm.py:689 -#: rhodecode/templates/switch_to_list.html:3 -#: rhodecode/templates/branches/branches.html:10 +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 msgid "Branches" msgstr "" -#: rhodecode/controllers/files.py:707 rhodecode/controllers/pullrequests.py:150 -#: rhodecode/controllers/summary.py:77 rhodecode/model/scm.py:700 -#: rhodecode/templates/switch_to_list.html:25 -#: rhodecode/templates/tags/tags.html:10 +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 msgid "Tags" msgstr "" -#: rhodecode/controllers/forks.py:176 -#, python-format -msgid "Forked repository %s as %s" -msgstr "" - -#: rhodecode/controllers/forks.py:190 +#: kallithea/controllers/forks.py:191 #, python-format msgid "An error occurred during repository forking %s" msgstr "" -#: rhodecode/controllers/journal.py:110 rhodecode/controllers/journal.py:153 +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 msgid "public journal" msgstr "" -#: rhodecode/controllers/journal.py:114 rhodecode/controllers/journal.py:157 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 msgid "journal" msgstr "" -#: rhodecode/controllers/login.py:145 -msgid "You have successfully registered into RhodeCode" -msgstr "" - -#: rhodecode/controllers/login.py:172 +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" +msgstr "" + +#: kallithea/controllers/login.py:237 msgid "Your password reset link was sent" msgstr "" -#: rhodecode/controllers/login.py:192 +#: kallithea/controllers/login.py:257 msgid "Your password reset was successful, new password has been sent to your email" msgstr "" -#: rhodecode/controllers/pullrequests.py:136 -#: rhodecode/templates/changeset/changeset.html:10 -#: rhodecode/templates/email_templates/changeset_comment.html:15 +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 msgid "Changeset" msgstr "" -#: rhodecode/controllers/pullrequests.py:146 +#: kallithea/controllers/pullrequests.py:157 msgid "Special" msgstr "" -#: rhodecode/controllers/pullrequests.py:147 +#: kallithea/controllers/pullrequests.py:158 msgid "Peer branches" msgstr "" -#: rhodecode/controllers/pullrequests.py:148 rhodecode/model/scm.py:695 -#: rhodecode/templates/switch_to_list.html:38 -#: rhodecode/templates/bookmarks/bookmarks.html:10 +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 msgid "Bookmarks" msgstr "" -#: rhodecode/controllers/pullrequests.py:323 +#: kallithea/controllers/pullrequests.py:330 msgid "Pull request requires a title with min. 3 chars" msgstr "" -#: rhodecode/controllers/pullrequests.py:325 +#: kallithea/controllers/pullrequests.py:332 #, python-format msgid "Error creating pull request: %s" msgstr "" -#: rhodecode/controllers/pullrequests.py:347 +#: kallithea/controllers/pullrequests.py:354 msgid "Successfully opened new pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:350 +#: kallithea/controllers/pullrequests.py:357 msgid "Error occurred during sending pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:389 +#: kallithea/controllers/pullrequests.py:397 msgid "Successfully deleted pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:477 +#: kallithea/controllers/pullrequests.py:485 msgid "Closing with" msgstr "" -#: rhodecode/controllers/pullrequests.py:514 +#: kallithea/controllers/pullrequests.py:522 msgid "Closing pull request on other statuses than rejected or approved forbidden" msgstr "" -#: rhodecode/controllers/search.py:132 +#: kallithea/controllers/search.py:135 msgid "Invalid search query. Try quoting it." msgstr "" -#: rhodecode/controllers/search.py:137 +#: kallithea/controllers/search.py:140 msgid "There is no index to search in. Please run whoosh indexer" msgstr "" -#: rhodecode/controllers/search.py:141 +#: kallithea/controllers/search.py:144 msgid "An error occurred during this search operation" msgstr "" -#: rhodecode/controllers/summary.py:182 +#: kallithea/controllers/summary.py:203 msgid "No data loaded yet" msgstr "" -#: rhodecode/controllers/summary.py:188 -#: rhodecode/templates/summary/summary.html:149 +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 msgid "Statistics are disabled for this repository" msgstr "" -#: rhodecode/controllers/admin/defaults.py:96 +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:97 msgid "Default settings updated successfully" msgstr "" -#: rhodecode/controllers/admin/defaults.py:110 +#: kallithea/controllers/admin/defaults.py:111 msgid "Error occurred during update of defaults" msgstr "" -#: rhodecode/controllers/admin/gists.py:56 +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 msgid "forever" msgstr "" -#: rhodecode/controllers/admin/gists.py:57 +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 msgid "5 minutes" msgstr "" -#: rhodecode/controllers/admin/gists.py:58 +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 msgid "1 hour" msgstr "" -#: rhodecode/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 msgid "1 day" msgstr "" -#: rhodecode/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 msgid "1 month" msgstr "" -#: rhodecode/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 msgid "Lifetime" msgstr "" -#: rhodecode/controllers/admin/gists.py:128 +#: kallithea/controllers/admin/gists.py:147 msgid "Error occurred during gist creation" msgstr "" -#: rhodecode/controllers/admin/gists.py:166 +#: kallithea/controllers/admin/gists.py:185 #, python-format msgid "Deleted gist %s" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:50 -msgid "BASE" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:51 -msgid "ONELEVEL" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:52 -msgid "SUBTREE" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:56 -msgid "NEVER" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:57 -msgid "ALLOW" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:58 -msgid "TRY" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:59 -msgid "DEMAND" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:60 -msgid "HARD" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:64 -msgid "No encryption" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:65 -msgid "LDAPS connection" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:66 -msgid "START_TLS on LDAP connection" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:124 -msgid "LDAP settings updated successfully" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:128 -msgid "Unable to activate ldap. The \"python-ldap\" library is missing." -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:145 -msgid "Error occurred during update of ldap settings" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:58 -#: rhodecode/controllers/admin/permissions.py:62 -#: rhodecode/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 msgid "None" msgstr "" -#: rhodecode/controllers/admin/permissions.py:59 -#: rhodecode/controllers/admin/permissions.py:63 -#: rhodecode/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 msgid "Read" msgstr "" -#: rhodecode/controllers/admin/permissions.py:60 -#: rhodecode/controllers/admin/permissions.py:64 -#: rhodecode/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 msgid "Write" msgstr "" -#: rhodecode/controllers/admin/permissions.py:61 -#: rhodecode/controllers/admin/permissions.py:65 -#: rhodecode/controllers/admin/permissions.py:69 -#: rhodecode/templates/admin/defaults/defaults.html:9 -#: rhodecode/templates/admin/ldap/ldap.html:9 -#: rhodecode/templates/admin/permissions/permissions.html:9 -#: rhodecode/templates/admin/repos/repo_add.html:10 -#: rhodecode/templates/admin/repos/repo_add.html:14 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:13 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:9 -#: rhodecode/templates/admin/users/user_add.html:8 -#: rhodecode/templates/admin/users/user_edit.html:9 -#: rhodecode/templates/admin/users/user_edit.html:133 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/admin/users/users.html:85 -#: rhodecode/templates/admin/users_groups/users_group_add.html:8 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 -#: rhodecode/templates/admin/users_groups/users_groups.html:9 -#: rhodecode/templates/base/base.html:315 -#: rhodecode/templates/base/base.html:316 -#: rhodecode/templates/base/base.html:322 -#: rhodecode/templates/base/base.html:323 +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 msgid "Admin" msgstr "" -#: rhodecode/controllers/admin/permissions.py:72 -#: rhodecode/controllers/admin/permissions.py:83 -#: rhodecode/controllers/admin/permissions.py:86 -#: rhodecode/controllers/admin/permissions.py:89 -#: rhodecode/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 msgid "Disabled" msgstr "" -#: rhodecode/controllers/admin/permissions.py:74 +#: kallithea/controllers/admin/permissions.py:78 msgid "Allowed with manual account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:80 msgid "Allowed with automatic account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:79 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1439 rhodecode/model/db.py:1444 +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 msgid "Manual activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:80 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1440 rhodecode/model/db.py:1445 +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 msgid "Automatic activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:84 -#: rhodecode/controllers/admin/permissions.py:87 -#: rhodecode/controllers/admin/permissions.py:90 -#: rhodecode/controllers/admin/permissions.py:93 +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 msgid "Enabled" msgstr "" -#: rhodecode/controllers/admin/permissions.py:138 -msgid "Default permissions updated successfully" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:152 +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:139 msgid "Error occurred during update of permissions" msgstr "" -#: rhodecode/controllers/admin/repos.py:128 -msgid "--REMOVE FORK--" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:168 +#: kallithea/controllers/admin/repo_groups.py:186 +#, python-format +msgid "Created repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:198 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:256 +#, python-format +msgid "Updated repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:271 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:289 +#, python-format +msgid "This group contains %s repositores and cannot be deleted" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:296 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:302 +#, python-format +msgid "Removed repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:237 #, python-format msgid "Created repository %s from %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:174 +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:249 #, python-format msgid "Created repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:197 -#, python-format -msgid "Error creating repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:270 +#: kallithea/controllers/admin/repos.py:289 #, python-format msgid "Repository %s updated successfully" msgstr "" -#: rhodecode/controllers/admin/repos.py:288 +#: kallithea/controllers/admin/repos.py:307 #, python-format msgid "Error occurred during update of repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:315 +#: kallithea/controllers/admin/repos.py:334 #, python-format msgid "Detached %s forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:318 +#: kallithea/controllers/admin/repos.py:337 #, python-format msgid "Deleted %s forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:323 +#: kallithea/controllers/admin/repos.py:342 #, python-format msgid "Deleted repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:326 +#: kallithea/controllers/admin/repos.py:345 #, python-format msgid "Cannot delete %s it still contains attached forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:331 +#: kallithea/controllers/admin/repos.py:350 #, python-format msgid "An error occurred during deletion of %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:345 +#: kallithea/controllers/admin/repos.py:402 msgid "Repository permissions updated" msgstr "" -#: rhodecode/controllers/admin/repos.py:375 -#: rhodecode/controllers/admin/repos_groups.py:332 -#: rhodecode/controllers/admin/users_groups.py:312 -msgid "An error occurred during revoking of permission" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:392 -msgid "An error occurred during deletion of repository stats" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:409 -msgid "An error occurred during cache invalidation" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:429 -#: rhodecode/controllers/admin/repos.py:456 -msgid "An error occurred during unlocking" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:447 -msgid "Unlocked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:450 -msgid "Locked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:452 -#, python-format -msgid "Repository has been %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:476 +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "" + +#: kallithea/controllers/admin/repos.py:522 msgid "Updated repository visibility in public journal" msgstr "" -#: rhodecode/controllers/admin/repos.py:480 +#: kallithea/controllers/admin/repos.py:526 msgid "An error occurred during setting this repository in public journal" msgstr "" -#: rhodecode/controllers/admin/repos.py:485 rhodecode/model/validators.py:302 +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 msgid "Token mismatch" msgstr "" -#: rhodecode/controllers/admin/repos.py:498 -msgid "Pulled from remote location" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:501 -msgid "An error occurred during pull from remote location" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:517 +#: kallithea/controllers/admin/repos.py:546 msgid "Nothing" msgstr "" -#: rhodecode/controllers/admin/repos.py:519 +#: kallithea/controllers/admin/repos.py:548 #, python-format msgid "Marked repo %s as fork of %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:523 +#: kallithea/controllers/admin/repos.py:555 msgid "An error occurred during this operation" msgstr "" -#: rhodecode/controllers/admin/repos.py:562 -msgid "An error occurred during creation of field" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:576 -msgid "An error occurred during removal of field" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:147 -#, python-format -msgid "Created repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:159 -#, python-format -msgid "Error occurred during creation of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:217 -#, python-format -msgid "Updated repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:232 -#, python-format -msgid "Error occurred during update of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:250 -#, python-format -msgid "This group contains %s repositores and cannot be deleted" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:257 -#, python-format -msgid "This group contains %s subgroups and cannot be deleted" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:263 -#, python-format -msgid "Removed repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:268 -#, python-format -msgid "Error occurred during deletion of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:279 -#: rhodecode/controllers/admin/repos_groups.py:314 -#: rhodecode/controllers/admin/users_groups.py:300 -msgid "Cannot revoke permission for yourself as admin" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:294 -msgid "Repository Group permissions updated" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:127 +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 +msgid "An error occurred during unlocking" +msgstr "" + +#: kallithea/controllers/admin/repos.py:595 +msgid "Unlocked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:598 +msgid "Locked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:600 +#, python-format +msgid "Repository has been %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "" + +#: kallithea/controllers/admin/repos.py:637 +msgid "Pulled from remote location" +msgstr "" + +#: kallithea/controllers/admin/repos.py:640 +msgid "An error occurred during pull from remote location" +msgstr "" + +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "" + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:176 +msgid "Unable to activate hgsubversion support. The \"hgsubversion\" library is missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:215 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" msgstr "" -#: rhodecode/controllers/admin/settings.py:136 -msgid "Whoosh reindex task scheduled" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:167 +#: kallithea/controllers/admin/settings.py:270 msgid "Updated application settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:171 -#: rhodecode/controllers/admin/settings.py:308 -msgid "Error occurred during updating application settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:223 +#: kallithea/controllers/admin/settings.py:327 msgid "Updated visualisation settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:228 +#: kallithea/controllers/admin/settings.py:332 msgid "Error occurred during updating visualisation settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:304 -msgid "Updated VCS settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:319 +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "" + +#: kallithea/controllers/admin/settings.py:400 msgid "Added new hook" msgstr "" -#: rhodecode/controllers/admin/settings.py:331 +#: kallithea/controllers/admin/settings.py:414 msgid "Updated hooks" msgstr "" -#: rhodecode/controllers/admin/settings.py:335 +#: kallithea/controllers/admin/settings.py:418 msgid "Error occurred during hook creation" msgstr "" -#: rhodecode/controllers/admin/settings.py:354 -msgid "Email task created" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:418 -msgid "You can't edit this user since it's crucial for entire application" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:460 -msgid "Your account was updated successfully" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:475 -#: rhodecode/controllers/admin/users.py:200 -#, python-format -msgid "Error occurred during update of user %s" -msgstr "" - -#: rhodecode/controllers/admin/users.py:130 +#: kallithea/controllers/admin/settings.py:444 +msgid "Whoosh reindex task scheduled" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:150 +#, python-format +msgid "Created user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:161 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Updated user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:221 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:239 +msgid "Successfully deleted user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:244 +msgid "An error occurred during deletion of user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:311 +msgid "Target group cannot be the same" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:317 +msgid "User Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "" + +#: kallithea/controllers/admin/users.py:135 #, python-format msgid "Created user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:144 +#: kallithea/controllers/admin/users.py:149 #, python-format msgid "Error occurred during creation of user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:178 +#: kallithea/controllers/admin/users.py:188 msgid "User updated successfully" msgstr "" -#: rhodecode/controllers/admin/users.py:216 +#: kallithea/controllers/admin/users.py:223 msgid "Successfully deleted user" msgstr "" -#: rhodecode/controllers/admin/users.py:221 +#: kallithea/controllers/admin/users.py:228 msgid "An error occurred during deletion of user" msgstr "" -#: rhodecode/controllers/admin/users.py:236 +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 msgid "You can't edit this user" msgstr "" -#: rhodecode/controllers/admin/users.py:295 -#: rhodecode/controllers/admin/users_groups.py:372 -msgid "Updated permissions" -msgstr "" - -#: rhodecode/controllers/admin/users.py:299 -#: rhodecode/controllers/admin/users_groups.py:376 -msgid "An error occurred during permissions saving" -msgstr "" - -#: rhodecode/controllers/admin/users.py:313 -#, python-format -msgid "Added email %s to user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:319 -msgid "An error occurred during email saving" -msgstr "" - -#: rhodecode/controllers/admin/users.py:329 -msgid "Removed email from user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:342 -#, python-format -msgid "Added ip %s to user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:348 +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "" + +#: kallithea/controllers/admin/users.py:489 msgid "An error occurred during ip saving" msgstr "" -#: rhodecode/controllers/admin/users.py:360 -msgid "Removed ip from user" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:162 -#, python-format -msgid "Created user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:173 -#, python-format -msgid "Error occurred during creation of user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:210 -#, python-format -msgid "Updated user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:232 -#, python-format -msgid "Error occurred during update of user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:250 -msgid "Successfully deleted user group" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:255 -msgid "An error occurred during deletion of user group" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:274 -msgid "Target group cannot be the same" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:280 -msgid "User Group permissions updated" -msgstr "" - -#: rhodecode/lib/auth.py:543 +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "" + +#: kallithea/lib/auth.py:748 #, python-format msgid "IP %s not allowed" msgstr "" -#: rhodecode/lib/auth.py:592 +#: kallithea/lib/auth.py:809 msgid "You need to be a registered user to perform this action" msgstr "" -#: rhodecode/lib/auth.py:633 +#: kallithea/lib/auth.py:846 msgid "You need to be a signed in to view this page" msgstr "" -#: rhodecode/lib/diffs.py:66 +#: kallithea/lib/diffs.py:66 msgid "Binary file" msgstr "" -#: rhodecode/lib/diffs.py:82 +#: kallithea/lib/diffs.py:82 msgid "Changeset was too big and was cut off, use diff menu to display this diff" msgstr "" -#: rhodecode/lib/diffs.py:92 +#: kallithea/lib/diffs.py:92 msgid "No changes detected" msgstr "" -#: rhodecode/lib/helpers.py:538 -msgid "True" -msgstr "" - -#: rhodecode/lib/helpers.py:541 -msgid "False" -msgstr "" - -#: rhodecode/lib/helpers.py:579 +#: kallithea/lib/helpers.py:598 #, python-format msgid "Deleted branch: %s" msgstr "" -#: rhodecode/lib/helpers.py:582 +#: kallithea/lib/helpers.py:601 #, python-format msgid "Created tag: %s" msgstr "" -#: rhodecode/lib/helpers.py:595 +#: kallithea/lib/helpers.py:614 msgid "Changeset not found" msgstr "" -#: rhodecode/lib/helpers.py:645 +#: kallithea/lib/helpers.py:664 #, python-format msgid "Show all combined changesets %s->%s" msgstr "" -#: rhodecode/lib/helpers.py:651 +#: kallithea/lib/helpers.py:670 msgid "compare view" msgstr "" -#: rhodecode/lib/helpers.py:671 +#: kallithea/lib/helpers.py:690 msgid "and" msgstr "" -#: rhodecode/lib/helpers.py:672 +#: kallithea/lib/helpers.py:691 #, python-format msgid "%s more" msgstr "" -#: rhodecode/lib/helpers.py:673 rhodecode/templates/changelog/changelog.html:53 +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 msgid "revisions" msgstr "" -#: rhodecode/lib/helpers.py:697 +#: kallithea/lib/helpers.py:716 #, python-format msgid "fork name %s" msgstr "" -#: rhodecode/lib/helpers.py:714 -#: rhodecode/templates/pullrequests/pullrequest_show.html:8 +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 #, python-format msgid "Pull request #%s" msgstr "" -#: rhodecode/lib/helpers.py:724 +#: kallithea/lib/helpers.py:743 msgid "[deleted] repository" msgstr "" -#: rhodecode/lib/helpers.py:726 rhodecode/lib/helpers.py:738 +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 msgid "[created] repository" msgstr "" -#: rhodecode/lib/helpers.py:728 +#: kallithea/lib/helpers.py:747 msgid "[created] repository as fork" msgstr "" -#: rhodecode/lib/helpers.py:730 rhodecode/lib/helpers.py:740 +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 msgid "[forked] repository" msgstr "" -#: rhodecode/lib/helpers.py:732 rhodecode/lib/helpers.py:742 +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 msgid "[updated] repository" msgstr "" -#: rhodecode/lib/helpers.py:734 +#: kallithea/lib/helpers.py:753 msgid "[downloaded] archive from repository" msgstr "" -#: rhodecode/lib/helpers.py:736 +#: kallithea/lib/helpers.py:755 msgid "[delete] repository" msgstr "" -#: rhodecode/lib/helpers.py:744 +#: kallithea/lib/helpers.py:763 msgid "[created] user" msgstr "" -#: rhodecode/lib/helpers.py:746 +#: kallithea/lib/helpers.py:765 msgid "[updated] user" msgstr "" -#: rhodecode/lib/helpers.py:748 +#: kallithea/lib/helpers.py:767 msgid "[created] user group" msgstr "" -#: rhodecode/lib/helpers.py:750 +#: kallithea/lib/helpers.py:769 msgid "[updated] user group" msgstr "" -#: rhodecode/lib/helpers.py:752 +#: kallithea/lib/helpers.py:771 msgid "[commented] on revision in repository" msgstr "" -#: rhodecode/lib/helpers.py:754 +#: kallithea/lib/helpers.py:773 msgid "[commented] on pull request for" msgstr "" -#: rhodecode/lib/helpers.py:756 +#: kallithea/lib/helpers.py:775 msgid "[closed] pull request for" msgstr "" -#: rhodecode/lib/helpers.py:758 +#: kallithea/lib/helpers.py:777 msgid "[pushed] into" msgstr "" -#: rhodecode/lib/helpers.py:760 -msgid "[committed via RhodeCode] into repository" -msgstr "" - -#: rhodecode/lib/helpers.py:762 +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "" + +#: kallithea/lib/helpers.py:781 msgid "[pulled from remote] into repository" msgstr "" -#: rhodecode/lib/helpers.py:764 +#: kallithea/lib/helpers.py:783 msgid "[pulled] from" msgstr "" -#: rhodecode/lib/helpers.py:766 +#: kallithea/lib/helpers.py:785 msgid "[started following] repository" msgstr "" -#: rhodecode/lib/helpers.py:768 +#: kallithea/lib/helpers.py:787 msgid "[stopped following] repository" msgstr "" -#: rhodecode/lib/helpers.py:1087 +#: kallithea/lib/helpers.py:1101 #, python-format msgid " and %s more" msgstr "" -#: rhodecode/lib/helpers.py:1091 +#: kallithea/lib/helpers.py:1105 msgid "No Files" msgstr "" -#: rhodecode/lib/helpers.py:1157 +#: kallithea/lib/helpers.py:1171 msgid "new file" msgstr "" -#: rhodecode/lib/helpers.py:1160 +#: kallithea/lib/helpers.py:1174 msgid "mod" msgstr "" -#: rhodecode/lib/helpers.py:1163 +#: kallithea/lib/helpers.py:1177 msgid "del" msgstr "" -#: rhodecode/lib/helpers.py:1166 +#: kallithea/lib/helpers.py:1180 msgid "rename" msgstr "" -#: rhodecode/lib/helpers.py:1171 +#: kallithea/lib/helpers.py:1185 msgid "chmod" msgstr "" -#: rhodecode/lib/helpers.py:1403 +#: kallithea/lib/helpers.py:1417 #, python-format msgid "%s repository is not mapped to db perhaps it was created or renamed from the filesystem please run the application again in order to rescan repositories" msgstr "" -#: rhodecode/lib/utils2.py:410 +#: kallithea/lib/utils2.py:415 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:411 +#: kallithea/lib/utils2.py:416 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:412 +#: kallithea/lib/utils2.py:417 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:413 +#: kallithea/lib/utils2.py:418 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:414 +#: kallithea/lib/utils2.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:415 +#: kallithea/lib/utils2.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: rhodecode/lib/utils2.py:431 +#: kallithea/lib/utils2.py:436 #, python-format msgid "in %s" msgstr "" -#: rhodecode/lib/utils2.py:433 +#: kallithea/lib/utils2.py:438 #, python-format msgid "%s ago" msgstr "" -#: rhodecode/lib/utils2.py:435 +#: kallithea/lib/utils2.py:440 #, python-format msgid "in %s and %s" msgstr "" -#: rhodecode/lib/utils2.py:438 +#: kallithea/lib/utils2.py:443 #, python-format msgid "%s and %s ago" msgstr "" -#: rhodecode/lib/utils2.py:441 +#: kallithea/lib/utils2.py:446 msgid "just now" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1163 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1303 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1388 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1408 rhodecode/model/db.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 msgid "Repository no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1164 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1184 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1304 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1389 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1409 rhodecode/model/db.py:1414 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 msgid "Repository read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1165 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1185 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1305 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1390 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1410 rhodecode/model/db.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 msgid "Repository write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1166 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1186 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1306 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1391 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1411 rhodecode/model/db.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 msgid "Repository admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1168 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 msgid "Repositories Group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1169 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1309 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 msgid "Repositories Group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1170 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1310 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 msgid "Repositories Group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1171 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1311 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 msgid "Repositories Group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1173 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1193 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1313 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1398 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1406 rhodecode/model/db.py:1411 -msgid "RhodeCode Administrator" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1174 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1194 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1314 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1399 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1429 rhodecode/model/db.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 msgid "Repository creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1175 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1195 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1315 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1400 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1430 rhodecode/model/db.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 msgid "Repository creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1176 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1196 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1316 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1401 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1432 rhodecode/model/db.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 msgid "Repository forking disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1177 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1197 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1317 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1402 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1433 rhodecode/model/db.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 msgid "Repository forking enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1178 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1318 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 msgid "Register disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1319 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1404 -msgid "Register new user with RhodeCode with manual activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1202 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1407 -msgid "Register new user with RhodeCode with auto activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1623 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1643 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1763 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1838 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1934 rhodecode/model/db.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 msgid "Not Reviewed" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1624 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1644 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1764 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1839 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1935 rhodecode/model/db.py:1940 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 msgid "Approved" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1625 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1645 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1765 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1840 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1936 rhodecode/model/db.py:1941 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 msgid "Rejected" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1626 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1646 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1766 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1841 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1937 rhodecode/model/db.py:1942 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 msgid "Under Review" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1252 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1270 rhodecode/model/db.py:1275 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 msgid "top level" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1393 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1413 rhodecode/model/db.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 msgid "Repository group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1394 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1414 rhodecode/model/db.py:1419 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 msgid "Repository group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1395 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1415 rhodecode/model/db.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 msgid "Repository group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1396 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1416 rhodecode/model/db.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 msgid "Repository group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1418 rhodecode/model/db.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 msgid "User group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1419 rhodecode/model/db.py:1424 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 msgid "User group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1420 rhodecode/model/db.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 msgid "User group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1421 rhodecode/model/db.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 msgid "User group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1423 rhodecode/model/db.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 msgid "Repository Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1424 rhodecode/model/db.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 msgid "Repository Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1426 rhodecode/model/db.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 msgid "User Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1427 rhodecode/model/db.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 msgid "User Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1435 rhodecode/model/db.py:1440 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 msgid "Registration disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1436 rhodecode/model/db.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 msgid "User Registration with manual account activation" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1437 rhodecode/model/db.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 msgid "User Registration with automatic account activation" msgstr "" -#: rhodecode/model/comment.py:75 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:77 #, python-format msgid "on line %s" msgstr "" -#: rhodecode/model/comment.py:220 +#: kallithea/model/comment.py:222 msgid "[Mention]" msgstr "" -#: rhodecode/model/forms.py:43 +#: kallithea/model/forms.py:57 msgid "Please enter a login" msgstr "" -#: rhodecode/model/forms.py:44 +#: kallithea/model/forms.py:58 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "" -#: rhodecode/model/forms.py:52 +#: kallithea/model/forms.py:66 msgid "Please enter a password" msgstr "" -#: rhodecode/model/forms.py:53 +#: kallithea/model/forms.py:67 #, python-format msgid "Enter %(min)i characters or more" msgstr "" -#: rhodecode/model/notification.py:228 +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:231 #, python-format msgid "%(user)s commented on changeset at %(when)s" msgstr "" -#: rhodecode/model/notification.py:229 +#: kallithea/model/notification.py:232 #, python-format msgid "%(user)s sent message at %(when)s" msgstr "" -#: rhodecode/model/notification.py:230 +#: kallithea/model/notification.py:233 #, python-format msgid "%(user)s mentioned you at %(when)s" msgstr "" -#: rhodecode/model/notification.py:231 -#, python-format -msgid "%(user)s registered in RhodeCode at %(when)s" -msgstr "" - -#: rhodecode/model/notification.py:232 +#: kallithea/model/notification.py:234 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:235 #, python-format msgid "%(user)s opened new pull request at %(when)s" msgstr "" -#: rhodecode/model/notification.py:233 +#: kallithea/model/notification.py:236 #, python-format msgid "%(user)s commented on pull request at %(when)s" msgstr "" -#: rhodecode/model/pull_request.py:105 +#: kallithea/model/pull_request.py:107 #, python-format msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" msgstr "" -#: rhodecode/model/scm.py:681 +#: kallithea/model/scm.py:810 msgid "latest tip" msgstr "" -#: rhodecode/model/user.py:294 +#: kallithea/model/user.py:198 msgid "New user registration" msgstr "" -#: rhodecode/model/user.py:318 rhodecode/model/user.py:342 +#: kallithea/model/user.py:222 kallithea/model/user.py:247 msgid "You can't Edit this user since it's crucial for entire application" msgstr "" -#: rhodecode/model/user.py:366 +#: kallithea/model/user.py:270 msgid "You can't remove this user since it's crucial for entire application" msgstr "" -#: rhodecode/model/user.py:372 +#: kallithea/model/user.py:276 #, python-format msgid "user \"%s\" still owns %s repositories and cannot be removed. Switch owners or remove those repositories. %s" msgstr "" -#: rhodecode/model/user.py:400 +#: kallithea/model/user.py:304 msgid "Password reset link" msgstr "" -#: rhodecode/model/user.py:430 +#: kallithea/model/user.py:333 msgid "Your new password" msgstr "" -#: rhodecode/model/user.py:431 -#, python-format -msgid "Your new RhodeCode password:%s" -msgstr "" - -#: rhodecode/model/validators.py:38 rhodecode/model/validators.py:39 +#: kallithea/model/user.py:334 +#, python-format +msgid "Your new Kallithea password:%s" +msgstr "" + +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 msgid "Value cannot be an empty list" msgstr "" -#: rhodecode/model/validators.py:85 +#: kallithea/model/validators.py:120 #, python-format msgid "Username \"%(username)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:87 +#: kallithea/model/validators.py:122 #, python-format msgid "Username \"%(username)s\" is forbidden" msgstr "" -#: rhodecode/model/validators.py:89 +#: kallithea/model/validators.py:124 msgid "Username may only contain alphanumeric characters underscores, periods or dashes and must begin with alphanumeric character or underscore" msgstr "" -#: rhodecode/model/validators.py:117 +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:158 #, python-format msgid "Username %(username)s is not valid" msgstr "" -#: rhodecode/model/validators.py:136 +#: kallithea/model/validators.py:177 msgid "Invalid user group name" msgstr "" -#: rhodecode/model/validators.py:137 +#: kallithea/model/validators.py:178 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:139 +#: kallithea/model/validators.py:180 msgid "user group name may only contain alphanumeric characters underscores, periods or dashes and must begin with alphanumeric character" msgstr "" -#: rhodecode/model/validators.py:177 +#: kallithea/model/validators.py:218 msgid "Cannot assign this group as parent" msgstr "" -#: rhodecode/model/validators.py:178 +#: kallithea/model/validators.py:219 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:180 +#: kallithea/model/validators.py:221 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:238 +#: kallithea/model/validators.py:279 msgid "Invalid characters (non-ascii) in password" msgstr "" -#: rhodecode/model/validators.py:253 +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 msgid "Passwords do not match" msgstr "" -#: rhodecode/model/validators.py:270 +#: kallithea/model/validators.py:327 msgid "invalid password" msgstr "" -#: rhodecode/model/validators.py:271 +#: kallithea/model/validators.py:328 msgid "invalid user name" msgstr "" -#: rhodecode/model/validators.py:272 +#: kallithea/model/validators.py:329 msgid "Your account is disabled" msgstr "" -#: rhodecode/model/validators.py:316 +#: kallithea/model/validators.py:373 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "" -#: rhodecode/model/validators.py:318 +#: kallithea/model/validators.py:375 #, python-format msgid "Repository named %(repo)s already exists" msgstr "" -#: rhodecode/model/validators.py:319 +#: kallithea/model/validators.py:376 #, python-format msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" msgstr "" -#: rhodecode/model/validators.py:321 +#: kallithea/model/validators.py:378 #, python-format msgid "Repository group with name \"%(repo)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:438 +#: kallithea/model/validators.py:493 msgid "invalid clone url" msgstr "" -#: rhodecode/model/validators.py:439 +#: kallithea/model/validators.py:494 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" msgstr "" -#: rhodecode/model/validators.py:464 +#: kallithea/model/validators.py:519 msgid "Fork have to be the same type as parent" msgstr "" -#: rhodecode/model/validators.py:479 +#: kallithea/model/validators.py:534 msgid "You don't have permissions to create repository in this group" msgstr "" -#: rhodecode/model/validators.py:481 +#: kallithea/model/validators.py:536 msgid "no permission to create repository in root location" msgstr "" -#: rhodecode/model/validators.py:518 +#: kallithea/model/validators.py:585 msgid "You don't have permissions to create a group in this location" msgstr "" -#: rhodecode/model/validators.py:559 +#: kallithea/model/validators.py:626 msgid "This username or user group name is not valid" msgstr "" -#: rhodecode/model/validators.py:652 +#: kallithea/model/validators.py:719 msgid "This is not a valid path" msgstr "" -#: rhodecode/model/validators.py:667 +#: kallithea/model/validators.py:734 msgid "This e-mail address is already taken" msgstr "" -#: rhodecode/model/validators.py:687 +#: kallithea/model/validators.py:754 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "" -#: rhodecode/model/validators.py:724 +#: kallithea/model/validators.py:791 msgid "The LDAP Login attribute of the CN must be specified - this is the name of the attribute that is equivalent to \"username\"" msgstr "" -#: rhodecode/model/validators.py:737 +#: kallithea/model/validators.py:804 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" msgstr "" -#: rhodecode/model/validators.py:769 +#: kallithea/model/validators.py:836 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "" -#: rhodecode/model/validators.py:770 +#: kallithea/model/validators.py:837 #, python-format msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" msgstr "" -#: rhodecode/model/validators.py:803 +#: kallithea/model/validators.py:870 msgid "Key name can only consist of letters, underscore, dash or numbers" msgstr "" -#: rhodecode/model/validators.py:817 +#: kallithea/model/validators.py:884 msgid "Filename cannot be inside a directory" msgstr "" -#: rhodecode/templates/index.html:5 +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" +msgstr "" + +#: kallithea/templates/index.html:5 msgid "Dashboard" msgstr "" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/repo_switcher_list.html:4 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/users/user_edit_my_account.html:31 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/bookmarks/bookmarks.html:9 -#: rhodecode/templates/branches/branches.html:9 -#: rhodecode/templates/journal/journal.html:9 -#: rhodecode/templates/journal/journal.html:46 -#: rhodecode/templates/journal/journal.html:47 -#: rhodecode/templates/tags/tags.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 msgid "quick filter..." msgstr "" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/admin/repos/repos.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 msgid "repositories" msgstr "" -#: rhodecode/templates/index_base.html:13 -#: rhodecode/templates/index_base.html:18 -#: rhodecode/templates/admin/repos/repo_add.html:5 -#: rhodecode/templates/admin/repos/repos.html:22 -msgid "Add repository" -msgstr "" - -#: rhodecode/templates/index_base.html:15 -#: rhodecode/templates/index_base.html:20 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:31 -msgid "Add repository group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5 -msgid "Edit repository group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" +msgstr "" + +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:32 msgid "You have admin right to this group, and can edit it" msgstr "" -#: rhodecode/templates/index_base.html:40 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:33 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:38 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:43 -#: rhodecode/templates/admin/users_groups/users_group_add.html:32 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 -#: rhodecode/templates/admin/users_groups/users_groups.html:37 -msgid "Group name" -msgstr "" - -#: rhodecode/templates/index_base.html:41 -#: rhodecode/templates/index_base.html:123 -#: rhodecode/templates/admin/repos/repo_add_base.html:56 -#: rhodecode/templates/admin/repos/repo_edit.html:68 -#: rhodecode/templates/admin/repos/repos.html:75 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:42 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:47 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:44 -#: rhodecode/templates/email_templates/changeset_comment.html:16 -#: rhodecode/templates/email_templates/pull_request.html:9 -#: rhodecode/templates/forks/fork.html:56 -#: rhodecode/templates/pullrequests/pullrequest.html:43 -#: rhodecode/templates/pullrequests/pullrequest_show.html:88 -#: rhodecode/templates/summary/summary.html:106 +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" +msgstr "" + +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 msgid "Description" msgstr "" -#: rhodecode/templates/index_base.html:51 -#: rhodecode/templates/admin/permissions/permissions.html:55 -#: rhodecode/templates/admin/repos/repo_add_base.html:29 -#: rhodecode/templates/admin/repos/repo_edit.html:50 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:57 -#: rhodecode/templates/forks/fork.html:47 -msgid "Repository group" -msgstr "" - -#: rhodecode/templates/index_base.html:121 -#: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit.html:32 -#: rhodecode/templates/admin/repos/repos.html:73 -#: rhodecode/templates/admin/users/user_edit_my_account.html:172 -#: rhodecode/templates/base/perms_summary.html:37 -#: rhodecode/templates/bookmarks/bookmarks.html:48 -#: rhodecode/templates/bookmarks/bookmarks_data.html:6 -#: rhodecode/templates/branches/branches.html:47 -#: rhodecode/templates/branches/branches_data.html:6 -#: rhodecode/templates/files/files_browser.html:47 -#: rhodecode/templates/journal/journal.html:193 -#: rhodecode/templates/journal/journal.html:283 -#: rhodecode/templates/summary/summary.html:55 -#: rhodecode/templates/summary/summary.html:124 -#: rhodecode/templates/tags/tags.html:48 -#: rhodecode/templates/tags/tags_data.html:6 +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 msgid "Name" msgstr "" -#: rhodecode/templates/index_base.html:124 +#: kallithea/templates/index_base.html:129 msgid "Last Change" msgstr "" -#: rhodecode/templates/index_base.html:126 -#: rhodecode/templates/admin/repos/repos.html:76 -#: rhodecode/templates/admin/users/user_edit_my_account.html:174 -#: rhodecode/templates/journal/journal.html:195 -#: rhodecode/templates/journal/journal.html:285 +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 msgid "Tip" msgstr "" -#: rhodecode/templates/index_base.html:128 -#: rhodecode/templates/admin/repos/repo_edit.html:114 -#: rhodecode/templates/admin/repos/repos.html:78 +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 msgid "Owner" msgstr "" -#: rhodecode/templates/index_base.html:136 -#: rhodecode/templates/admin/repos/repos.html:86 -#: rhodecode/templates/admin/users/user_edit_my_account.html:183 -#: rhodecode/templates/admin/users/users.html:107 -#: rhodecode/templates/bookmarks/bookmarks.html:74 -#: rhodecode/templates/branches/branches.html:73 -#: rhodecode/templates/journal/journal.html:204 -#: rhodecode/templates/journal/journal.html:294 -#: rhodecode/templates/tags/tags.html:74 +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 msgid "Click to sort ascending" msgstr "" -#: rhodecode/templates/index_base.html:137 -#: rhodecode/templates/admin/repos/repos.html:87 -#: rhodecode/templates/admin/users/user_edit_my_account.html:184 -#: rhodecode/templates/admin/users/users.html:108 -#: rhodecode/templates/bookmarks/bookmarks.html:75 -#: rhodecode/templates/branches/branches.html:74 -#: rhodecode/templates/journal/journal.html:205 -#: rhodecode/templates/journal/journal.html:295 -#: rhodecode/templates/tags/tags.html:75 +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 msgid "Click to sort descending" msgstr "" -#: rhodecode/templates/index_base.html:138 +#: kallithea/templates/index_base.html:143 msgid "No repositories found." msgstr "" -#: rhodecode/templates/index_base.html:139 -#: rhodecode/templates/admin/repos/repos.html:89 -#: rhodecode/templates/admin/users/user_edit_my_account.html:186 -#: rhodecode/templates/admin/users/users.html:110 -#: rhodecode/templates/bookmarks/bookmarks.html:77 -#: rhodecode/templates/branches/branches.html:76 -#: rhodecode/templates/journal/journal.html:207 -#: rhodecode/templates/journal/journal.html:297 -#: rhodecode/templates/tags/tags.html:77 +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 msgid "Data error." msgstr "" -#: rhodecode/templates/index_base.html:140 -#: rhodecode/templates/admin/repos/repos.html:90 -#: rhodecode/templates/admin/users/user_edit_my_account.html:58 -#: rhodecode/templates/admin/users/user_edit_my_account.html:187 -#: rhodecode/templates/admin/users/users.html:111 -#: rhodecode/templates/base/base.html:125 -#: rhodecode/templates/base/base.html:277 -#: rhodecode/templates/bookmarks/bookmarks.html:78 -#: rhodecode/templates/branches/branches.html:77 -#: rhodecode/templates/journal/journal.html:208 -#: rhodecode/templates/journal/journal.html:298 -#: rhodecode/templates/tags/tags.html:78 +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 msgid "Loading..." msgstr "" -#: rhodecode/templates/login.html:5 rhodecode/templates/base/base.html:237 +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 msgid "Log In" msgstr "" -#: rhodecode/templates/login.html:21 +#: kallithea/templates/login.html:30 #, python-format msgid "Log In to %s" msgstr "" -#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:29 -#: rhodecode/templates/admin/admin_log.html:5 -#: rhodecode/templates/admin/users/user_add.html:32 -#: rhodecode/templates/admin/users/user_edit.html:57 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:32 -#: rhodecode/templates/admin/users/users.html:77 -#: rhodecode/templates/base/base.html:213 -#: rhodecode/templates/summary/summary.html:123 +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 msgid "Username" msgstr "" -#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:38 -#: rhodecode/templates/admin/ldap/ldap.html:46 -#: rhodecode/templates/admin/users/user_add.html:41 -#: rhodecode/templates/base/base.html:222 +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 msgid "Password" msgstr "" -#: rhodecode/templates/login.html:50 +#: kallithea/templates/login.html:62 msgid "Remember me" msgstr "" -#: rhodecode/templates/login.html:54 +#: kallithea/templates/login.html:66 msgid "Sign In" msgstr "" -#: rhodecode/templates/login.html:60 +#: kallithea/templates/login.html:72 msgid "Forgot your password ?" msgstr "" -#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:233 +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 msgid "Don't have an account ?" msgstr "" -#: rhodecode/templates/password_reset.html:5 +#: kallithea/templates/password_reset.html:5 msgid "Password Reset" msgstr "" -#: rhodecode/templates/password_reset.html:11 -msgid "Reset your password to" -msgstr "" - -#: rhodecode/templates/password_reset.html:21 -msgid "Email address" -msgstr "" - -#: rhodecode/templates/password_reset.html:30 -msgid "Reset my password" -msgstr "" - -#: rhodecode/templates/password_reset.html:31 +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" +msgstr "" + +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "" + +#: kallithea/templates/password_reset.html:64 msgid "Password reset link will be send to matching email address" msgstr "" -#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:83 +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 msgid "Sign Up" msgstr "" -#: rhodecode/templates/register.html:20 -msgid "Sign Up to" -msgstr "" - -#: rhodecode/templates/register.html:47 +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:58 msgid "Re-enter password" msgstr "" -#: rhodecode/templates/register.html:56 -#: rhodecode/templates/admin/users/user_add.html:59 -#: rhodecode/templates/admin/users/user_edit.html:97 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:63 +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 msgid "First Name" msgstr "" -#: rhodecode/templates/register.html:65 -#: rhodecode/templates/admin/users/user_add.html:68 -#: rhodecode/templates/admin/users/user_edit.html:106 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:72 +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 msgid "Last Name" msgstr "" -#: rhodecode/templates/register.html:74 -#: rhodecode/templates/admin/users/user_add.html:77 -#: rhodecode/templates/admin/users/user_edit.html:115 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:81 -#: rhodecode/templates/summary/summary.html:125 +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 msgid "Email" msgstr "" -#: rhodecode/templates/register.html:85 +#: kallithea/templates/register.html:108 msgid "Your account will be activated right after registration" msgstr "" -#: rhodecode/templates/register.html:87 +#: kallithea/templates/register.html:110 msgid "Your account must wait for activation by administrator" msgstr "" -#: rhodecode/templates/repo_switcher_list.html:10 -#: rhodecode/templates/admin/defaults/defaults.html:44 -#: rhodecode/templates/admin/repos/repo_add_base.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:78 -#: rhodecode/templates/data_table/_dt_elements.html:61 -#: rhodecode/templates/summary/summary.html:77 -msgid "Private repository" -msgstr "" - -#: rhodecode/templates/repo_switcher_list.html:12 -#: rhodecode/templates/data_table/_dt_elements.html:63 -#: rhodecode/templates/summary/summary.html:79 -msgid "Public repository" -msgstr "" - -#: rhodecode/templates/switch_to_list.html:10 -#: rhodecode/templates/branches/branches_data.html:57 +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 msgid "There are no branches yet" msgstr "" -#: rhodecode/templates/switch_to_list.html:16 +#: kallithea/templates/switch_to_list.html:16 msgid "Closed Branches" msgstr "" -#: rhodecode/templates/switch_to_list.html:32 -#: rhodecode/templates/tags/tags_data.html:38 +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 msgid "There are no tags yet" msgstr "" -#: rhodecode/templates/switch_to_list.html:45 -#: rhodecode/templates/bookmarks/bookmarks_data.html:37 +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 msgid "There are no bookmarks yet" msgstr "" -#: rhodecode/templates/admin/admin.html:5 -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/base/base.html:71 +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 msgid "Admin journal" msgstr "" -#: rhodecode/templates/admin/admin.html:10 +#: kallithea/templates/admin/admin.html:13 msgid "journal filter..." msgstr "" -#: rhodecode/templates/admin/admin.html:12 -#: rhodecode/templates/journal/journal.html:11 +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 msgid "filter" msgstr "" -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 #, python-format msgid "%s entry" msgid_plural "%s entries" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/admin/admin_log.html:6 -#: rhodecode/templates/admin/repos/repos.html:79 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46 -#: rhodecode/templates/admin/users/user_edit_my_account.html:176 -#: rhodecode/templates/admin/users/users.html:87 -#: rhodecode/templates/admin/users_groups/users_groups.html:40 -#: rhodecode/templates/journal/journal.html:197 -#: rhodecode/templates/journal/journal.html:287 +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 msgid "Action" msgstr "" -#: rhodecode/templates/admin/admin_log.html:7 -#: rhodecode/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" msgstr "" -#: rhodecode/templates/admin/admin_log.html:8 -#: rhodecode/templates/bookmarks/bookmarks.html:49 -#: rhodecode/templates/bookmarks/bookmarks_data.html:7 -#: rhodecode/templates/branches/branches.html:48 -#: rhodecode/templates/branches/branches_data.html:7 -#: rhodecode/templates/tags/tags.html:49 -#: rhodecode/templates/tags/tags_data.html:7 +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 msgid "Date" msgstr "" -#: rhodecode/templates/admin/admin_log.html:9 +#: kallithea/templates/admin/admin_log.html:9 msgid "From IP" msgstr "" -#: rhodecode/templates/admin/admin_log.html:63 +#: kallithea/templates/admin/admin_log.html:63 msgid "No actions yet" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:5 -#: rhodecode/templates/admin/defaults/defaults.html:25 +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "Comma separated list of plugins. Order of plugins is also order in which Kallithea will try to authenticate user" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 msgid "Repositories defaults" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:11 -#: rhodecode/templates/base/base.html:78 +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 msgid "Defaults" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:35 -#: rhodecode/templates/admin/repos/repo_add_base.html:38 +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 msgid "Type" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:48 -#: rhodecode/templates/admin/repos/repo_add_base.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:82 -#: rhodecode/templates/forks/fork.html:69 +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 msgid "Private repositories are only visible to people explicitly added as collaborators." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:55 -#: rhodecode/templates/admin/repos/repo_edit.html:87 +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 msgid "Enable statistics" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:59 -#: rhodecode/templates/admin/repos/repo_edit.html:91 +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:96 +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 msgid "Enable downloads" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:100 +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:75 -#: rhodecode/templates/admin/repos/repo_edit.html:105 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:64 +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 msgid "Enable locking" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:79 -#: rhodecode/templates/admin/repos/repo_edit.html:109 +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 msgid "Enable lock-by-pulling on repository." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:84 -#: rhodecode/templates/admin/ldap/ldap.html:89 -#: rhodecode/templates/admin/permissions/permissions.html:122 -#: rhodecode/templates/admin/repos/repo_edit.html:141 -#: rhodecode/templates/admin/repos/repo_edit.html:166 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:72 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:96 -#: rhodecode/templates/admin/settings/hooks.html:73 -#: rhodecode/templates/admin/users/user_add.html:94 -#: rhodecode/templates/admin/users/user_edit.html:140 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:89 -#: rhodecode/templates/admin/users_groups/users_group_add.html:49 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:143 -#: rhodecode/templates/base/default_perms_box.html:53 -msgid "Save" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:5 -#: rhodecode/templates/base/base.html:297 -msgid "Gists" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "Gist was update since you started editing. Copy your changes and click %(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 #, python-format msgid "Private Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:12 +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 #, python-format msgid "Public Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:14 +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 msgid "Public Gists" msgstr "" -#: rhodecode/templates/admin/gists/index.html:31 -#: rhodecode/templates/admin/gists/show.html:24 -#: rhodecode/templates/base/base.html:300 -msgid "Create new gist" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:48 +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 msgid "Created" msgstr "" -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/index.html:53 -#: rhodecode/templates/admin/gists/show.html:43 -#: rhodecode/templates/admin/gists/show.html:45 -msgid "Expires" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/show.html:43 -msgid "never" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:68 +#: kallithea/templates/admin/gists/index.html:77 msgid "There are no gists yet" msgstr "" -#: rhodecode/templates/admin/gists/new.html:5 -#: rhodecode/templates/admin/gists/new.html:19 -msgid "New gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:40 -msgid "Gist description ..." -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:42 -msgid "Gist lifetime" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:51 -#: rhodecode/templates/files/files_add.html:75 -#: rhodecode/templates/files/files_edit.html:60 -msgid "plain" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:59 -msgid "Create private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:60 -msgid "Create public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:61 -#: rhodecode/templates/admin/permissions/permissions.html:123 -#: rhodecode/templates/admin/permissions/permissions.html:185 -#: rhodecode/templates/admin/repos/repo_edit.html:142 -#: rhodecode/templates/admin/repos/repo_edit.html:167 -#: rhodecode/templates/admin/repos/repo_edit.html:381 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:97 -#: rhodecode/templates/admin/settings/settings.html:121 -#: rhodecode/templates/admin/settings/settings.html:202 -#: rhodecode/templates/admin/settings/settings.html:297 -#: rhodecode/templates/admin/users/user_edit.html:141 -#: rhodecode/templates/admin/users/user_edit.html:198 -#: rhodecode/templates/admin/users/user_edit.html:246 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:144 -#: rhodecode/templates/base/default_perms_box.html:54 -#: rhodecode/templates/files/files_add.html:86 -#: rhodecode/templates/files/files_edit.html:69 -#: rhodecode/templates/pullrequests/pullrequest.html:86 +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 msgid "Reset" msgstr "" -#: rhodecode/templates/admin/gists/show.html:5 -msgid "gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:9 +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 msgid "Gist" msgstr "" -#: rhodecode/templates/admin/gists/show.html:36 -msgid "Public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:38 -msgid "Private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:54 -#: rhodecode/templates/admin/repos/repo_edit.html:299 -#: rhodecode/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 msgid "Delete" msgstr "" -#: rhodecode/templates/admin/gists/show.html:54 -msgid "Confirm to delete this gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:63 -#: rhodecode/templates/admin/gists/show.html:84 -#: rhodecode/templates/files/files_edit.html:50 -#: rhodecode/templates/files/files_source.html:25 -#: rhodecode/templates/files/files_source.html:55 -msgid "Show as raw" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:71 +#: kallithea/templates/admin/gists/show.html:59 +msgid "Confirm to delete this Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:76 msgid "created" msgstr "" -#: rhodecode/templates/admin/ldap/ldap.html:5 -msgid "LDAP administration" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:11 -#: rhodecode/templates/admin/users/users.html:86 -#: rhodecode/templates/base/base.html:77 -msgid "LDAP" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:28 -msgid "Connection settings" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:30 -msgid "Enable LDAP" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:34 -msgid "Host" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:38 -msgid "Port" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:42 -msgid "Account" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:50 -msgid "Connection security" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:54 -msgid "Certificate Checks" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:57 -msgid "Search settings" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:59 -msgid "Base DN" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:63 -msgid "LDAP Filter" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:67 -msgid "LDAP Search Scope" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:70 -msgid "Attribute mappings" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:72 -msgid "Login Attribute" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:76 -msgid "First Name Attribute" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:80 -msgid "Last Name Attribute" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:84 -msgid "E-mail Attribute" -msgstr "" - -#: rhodecode/templates/admin/notifications/notifications.html:5 -#: rhodecode/templates/admin/notifications/notifications.html:9 +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "Your user is in an external Source of Record; some details cannot be managed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 msgid "My Notifications" msgstr "" -#: rhodecode/templates/admin/notifications/notifications.html:29 +#: kallithea/templates/admin/notifications/notifications.html:32 msgid "All" msgstr "" -#: rhodecode/templates/admin/notifications/notifications.html:30 +#: kallithea/templates/admin/notifications/notifications.html:33 msgid "Comments" msgstr "" -#: rhodecode/templates/admin/notifications/notifications.html:31 -msgid "Pull requests" -msgstr "" - -#: rhodecode/templates/admin/notifications/notifications.html:35 +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:38 msgid "Mark all read" msgstr "" -#: rhodecode/templates/admin/notifications/notifications_data.html:39 +#: kallithea/templates/admin/notifications/notifications_data.html:40 msgid "No notifications here yet" msgstr "" -#: rhodecode/templates/admin/notifications/show_notification.html:5 -#: rhodecode/templates/admin/notifications/show_notification.html:11 +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 msgid "Show notification" msgstr "" -#: rhodecode/templates/admin/notifications/show_notification.html:9 -#: rhodecode/templates/base/base.html:251 +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 msgid "Notifications" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:5 msgid "Permissions administration" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:11 -#: rhodecode/templates/admin/repos/repo_edit.html:151 -#: rhodecode/templates/admin/repos/repo_edit.html:158 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:81 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:88 -#: rhodecode/templates/admin/users/user_edit.html:150 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:129 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:136 -#: rhodecode/templates/base/base.html:76 +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 msgid "Permissions" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:24 -msgid "Default permissions" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:31 +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 msgid "Anonymous access" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:49 +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "Allow access to Kallithea without need to log in. Anonymous users use %s user permissions" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 msgid "All default permissions on each repository will be reset to chosen permission, note that all custom default permission on repositories will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:50 -#: rhodecode/templates/admin/permissions/permissions.html:63 -#: rhodecode/templates/admin/permissions/permissions.html:77 +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 msgid "Overwrite existing settings" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:62 +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 msgid "All default permissions on each repository group will be reset to chosen permission, note that all custom default permission on repository groups will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 msgid "User group" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:76 +#: kallithea/templates/admin/permissions/permissions_globals.html:53 msgid "All default permissions on each user group will be reset to chosen permission, note that all custom default permission on repository groups will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:83 +#: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:91 +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "Write permission to repository groups allows creating repositories inside that group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 msgid "User group creation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:99 +#: kallithea/templates/admin/permissions/permissions_globals.html:85 msgid "Repository forking" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:107 +#: kallithea/templates/admin/permissions/permissions_globals.html:93 msgid "Registration" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:115 +#: kallithea/templates/admin/permissions/permissions_globals.html:101 msgid "External auth account activation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:133 -msgid "Default User Permissions" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:144 -#: rhodecode/templates/admin/users/user_edit.html:207 -msgid "Allowed IP addresses" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:158 -#: rhodecode/templates/admin/repos/repo_edit.html:340 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#: rhodecode/templates/admin/users/user_edit.html:175 -#: rhodecode/templates/admin/users/user_edit.html:220 -#: rhodecode/templates/admin/users_groups/users_groups.html:54 -#: rhodecode/templates/data_table/_dt_elements.html:122 -#: rhodecode/templates/data_table/_dt_elements.html:136 -msgid "delete" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:159 -#: rhodecode/templates/admin/users/user_edit.html:221 +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 #, python-format msgid "Confirm to delete this ip: %s" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:165 -#: rhodecode/templates/admin/users/user_edit.html:227 +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 msgid "All IP addresses are allowed" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:176 -#: rhodecode/templates/admin/users/user_edit.html:238 +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:184 -#: rhodecode/templates/admin/repos/repo_add_base.html:73 -#: rhodecode/templates/admin/repos/repo_edit.html:380 -#: rhodecode/templates/admin/users/user_edit.html:197 -#: rhodecode/templates/admin/users/user_edit.html:245 -msgid "Add" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add.html:12 -#: rhodecode/templates/admin/repos/repo_add.html:16 -#: rhodecode/templates/base/base.html:72 rhodecode/templates/base/base.html:86 -#: rhodecode/templates/base/base.html:114 -#: rhodecode/templates/base/base.html:273 -msgid "Repositories" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add.html:19 -msgid "Add new" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:20 -#: rhodecode/templates/summary/summary.html:96 -#: rhodecode/templates/summary/summary.html:97 -msgid "Clone from" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:24 -#: rhodecode/templates/admin/repos/repo_edit.html:45 -msgid "Optional http[s] url from which repository should be cloned." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:33 -#: rhodecode/templates/forks/fork.html:51 -msgid "Optionaly select a group to put this repository into." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:42 -msgid "Type of repository to create." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:47 -#: rhodecode/templates/admin/repos/repo_edit.html:59 -#: rhodecode/templates/forks/fork.html:38 -msgid "Landing revision" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:51 -#: rhodecode/templates/admin/repos/repo_edit.html:63 -#: rhodecode/templates/forks/fork.html:42 -msgid "Default revision for files page, downloads, whoosh and readme" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:60 -#: rhodecode/templates/admin/repos/repo_edit.html:72 -#: rhodecode/templates/forks/fork.html:60 -msgid "Keep it short and to the point. Use a README file for longer descriptions." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:8 -msgid "Edit repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:12 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:11 -#: rhodecode/templates/base/base.html:79 rhodecode/templates/base/base.html:132 -#: rhodecode/templates/summary/summary.html:212 +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 msgid "Settings" msgstr "" -#: rhodecode/templates/admin/repos/repo_edit.html:36 -msgid "Non-changeable id" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:41 -msgid "Clone uri" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:54 -msgid "Optional select a group to put this repository into." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:119 -msgid "Change owner of this repository." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:177 -msgid "Advanced settings" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:180 -msgid "Statistics" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Reset current statistics" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Confirm to remove current statistics" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:187 -msgid "Fetched to rev" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:188 -msgid "Stats gathered" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:196 -msgid "Remote" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Pull changes from remote location" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Confirm to pull changes from remote side" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:211 -msgid "Cache" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Invalidate repository cache" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Confirm to invalidate repository cache" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:218 -msgid "Manually invalidate cache for this repository. On first access repository will be cached again" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:223 -msgid "List of cached values" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:226 -msgid "Prefix" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:227 -msgid "Key" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:228 -#: rhodecode/templates/admin/users/user_add.html:86 -#: rhodecode/templates/admin/users/user_edit.html:124 -#: rhodecode/templates/admin/users/users.html:84 -#: rhodecode/templates/admin/users_groups/users_group_add.html:41 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 -#: rhodecode/templates/admin/users_groups/users_groups.html:39 -msgid "Active" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:243 -#: rhodecode/templates/base/base.html:290 -#: rhodecode/templates/base/base.html:291 -msgid "Public journal" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:249 -msgid "Remove from public journal" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:251 -msgid "Add to public journal" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:256 -msgid "All actions made on this repository will be accessible to everyone in public journal" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:263 -msgid "Locking" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Unlock locked repo" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Confirm to unlock repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Lock repo" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Confirm to lock repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:272 -msgid "Repository is not locked" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:277 -msgid "Force locking on repository. Works only when anonymous access is disabled" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:284 -msgid "Set as fork of" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:289 -msgid "Set" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:293 -msgid "Manually set this repository as a fork of another from the list" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Remove this repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Confirm to delete this repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:310 -#, python-format -msgid "this repository has %s fork" -msgid_plural "this repository has %s forks" -msgstr[0] "" -msgstr[1] "" - -#: rhodecode/templates/admin/repos/repo_edit.html:311 -msgid "Detach forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:312 -msgid "Delete forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:315 -msgid "This repository will be renamed in a special way in order to be unaccesible for RhodeCode and VCS systems. If you need to fully delete it from file system please do it manually" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:329 -msgid "Extra fields" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:341 -#, python-format -msgid "Confirm to delete this field: %s" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:355 -msgid "New field key" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:363 -msgid "New field label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:366 -msgid "Enter short label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:372 -msgid "New field description" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:375 -msgid "Enter description of a field" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:3 -msgid "none" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:4 -msgid "read" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:5 -msgid "write" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:6 -msgid "admin" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:7 -msgid "member" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:16 -msgid "private repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:19 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:28 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:20 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:35 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:20 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:35 -msgid "default" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:33 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:58 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:25 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:55 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:25 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:55 -msgid "revoke" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:83 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:81 -msgid "Add another member" -msgstr "" - -#: rhodecode/templates/admin/repos/repos.html:5 -msgid "Repositories administration" -msgstr "" - -#: rhodecode/templates/admin/repos/repos.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account.html:185 -#: rhodecode/templates/admin/users/users.html:109 -#: rhodecode/templates/bookmarks/bookmarks.html:76 -#: rhodecode/templates/branches/branches.html:75 -#: rhodecode/templates/journal/journal.html:206 -#: rhodecode/templates/journal/journal.html:296 -#: rhodecode/templates/tags/tags.html:76 -msgid "No records found." -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:87 -msgid "apply to children" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:88 -msgid "Set or revoke permission to all children of that group, including non-private repositories and other groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:4 -#, python-format -msgid "%s Group Dashboard" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:9 -msgid "Home" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:13 -msgid "with" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:16 -#: rhodecode/templates/base/base.html:73 rhodecode/templates/base/base.html:89 -msgid "Repository groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:13 -msgid "Add new repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:51 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:56 -msgid "Group parent" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:59 -msgid "save" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:13 -#, python-format -msgid "Edit repository group %s" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:27 -msgid "Add child group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:68 -msgid "Enable lock-by-pulling on group. This option will be applied to all other groups and repositories inside" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5 -msgid "Repository groups administration" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:45 -msgid "Number of toplevel repositories" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:64 -#: rhodecode/templates/admin/users_groups/users_groups.html:48 -#: rhodecode/templates/changeset/changeset_file_comment.html:81 -#: rhodecode/templates/changeset/changeset_file_comment.html:189 -msgid "Edit" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:65 -#: rhodecode/templates/admin/users_groups/users_groups.html:49 -#: rhodecode/templates/base/perms_summary.html:29 -#: rhodecode/templates/base/perms_summary.html:60 -#: rhodecode/templates/base/perms_summary.html:62 -#: rhodecode/templates/data_table/_dt_elements.html:116 -#: rhodecode/templates/data_table/_dt_elements.html:117 -#: rhodecode/templates/data_table/_dt_elements.html:130 -#: rhodecode/templates/data_table/_dt_elements.html:131 -msgid "edit" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 #, python-format msgid "Confirm to delete this group: %s with %s repository" msgid_plural "Confirm to delete this group: %s with %s repositories" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:78 -msgid "There are no repository groups yet" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:5 -#: rhodecode/templates/admin/settings/settings.html:5 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "Set or revoke permission to all children of that group, including non-private repositories and other groups if selected." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "Enable lock-by-pulling on group. This option will be applied to all other groups and repositories inside" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "%s Repository group dashboard" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "Default revision for files page, downloads, full text search index and readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "Repository \"%(repo_name)s\" is beeing created, you will be redirected when this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:42 +msgid "We're sorry but error occured during this operation. Please check your Kallithea server logs, or contact administrator." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, python-format +msgid "%s repository settings" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +msgid "Remote" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Remove from public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +msgid "Add to public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 +msgid "All actions made on this repository will be accessible to everyone in public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 +msgid "Confirm to unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 +msgid "Confirm to lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 +msgid "Repository is not locked" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 +msgid "Force locking on repository. Works only when anonymous access is disabled. Trigering a pull locks repository by user who pulled, only the same user can unlock by doing a push" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +msgid "Delete this repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 +#, python-format +msgid "this repository has %s fork" +msgid_plural "this repository has %s forks" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 +msgid "Detach forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 +msgid "Delete forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "This repository will be renamed in a special way in order to be unaccesible for Kallithea and VCS systems. If you need to fully delete it from file system please do it manually" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 +msgid "Manually invalidate cache for this repository. On first access repository will be cached again" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#, python-format +msgid "Confirm to delete this field: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 +msgid "New field key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 +msgid "New field label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 +msgid "Enter short label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 +msgid "New field description" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +msgid "Enter description of a field" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 +msgid "private repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 +msgid "" +"In case this repository is renamed or moved into another group the repository url changes.\n" +" Using above url guarantees that this repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases that you need to hardcode the url into 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "" + +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 msgid "Settings administration" msgstr "" -#: rhodecode/templates/admin/settings/hooks.html:24 -msgid "Built in hooks - read only" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:40 -msgid "Custom hooks" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:56 -msgid "remove" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:89 -msgid "Failed to remove hook" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:26 -msgid "Remap and rescan repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:34 -msgid "Rescan option" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:40 -msgid "In case a repository was deleted from filesystem and there are leftovers in the database check this option to scan obsolete data in database and remove it." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:41 -msgid "Destroy old data" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:46 -msgid "Invalidate cache for all repositories during scan" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:47 -msgid "Invalidate cache for all repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:49 -msgid "Rescan repositories location for new repositories. Also deletes obsolete if `destroy` flag is checked " -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:54 -msgid "Rescan repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:60 -msgid "Whoosh indexing" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:68 -msgid "Index build option" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:73 -msgid "Build from scratch" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:79 -msgid "Reindex" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:85 -msgid "Global application settings" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:94 +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:16 +msgid "SMTP auth" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:39 +msgid "Send" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:8 msgid "Site branding" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:103 +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:18 msgid "HTTP authentication realm" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:112 +#: kallithea/templates/admin/settings/settings_global.html:27 msgid "Google Analytics code" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:120 -#: rhodecode/templates/admin/settings/settings.html:201 -#: rhodecode/templates/admin/settings/settings.html:296 +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:50 +msgid "Private key for reCaptcha system. Setting this value will enable captcha on registration" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 msgid "Save settings" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:127 -msgid "Visualisation settings" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:135 -msgid "General" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:140 -msgid "Use repository extra fields" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:142 -msgid "Allows storing additional customized fields per repository." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:145 -msgid "Show RhodeCode version" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:147 -msgid "Shows or hides displayed version of RhodeCode in the footer" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:152 -msgid "Dashboard items" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:156 -msgid "Number of items displayed in lightweight dashboard before pagination is shown." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:161 -msgid "Icons" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:166 -msgid "Show public repo icon on repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:170 -msgid "Show private repo icon on repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:172 -msgid "Show public/private icons next to repositories names" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:178 -msgid "Meta-Tagging" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:183 -msgid "Stylify recognised metatags:" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:210 -msgid "VCS settings" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:219 +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "Hooks can be used to trigger actions on certain events such as push / pull. They can trigger Python functions or external applications." +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 +msgid "Custom hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:69 +msgid "Failed to remove hook" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:6 +msgid "Rescan option" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:11 +msgid "Destroy old data" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:13 +msgid "In case a repository was deleted from filesystem and it still exists in the database check this option to scan obsolete data in database and remove it." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 +msgid "Each cache data for repositories will be cleaned with this option selected. Use this to reload data and clear cache keys." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 +msgid "Verify if Kallitheas GIT hooks are installed for each repository. Current hooks will be updated to latest version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:7 +msgid "Index build option" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:12 +msgid "Build from scratch" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:15 +msgid "This option completely reindex all the files within Kallithea for proper fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:21 +msgid "Reindex" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 msgid "Web" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:224 +#: kallithea/templates/admin/settings/settings_vcs.html:11 msgid "Require SSL for vcs operations" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:226 -msgid "RhodeCode will require SSL for pushing or pulling. If SSL is missing it will return HTTP Error 406: Not Acceptable" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:232 -msgid "Hooks" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:237 -msgid "Update repository after push (hg update)" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:241 +#: kallithea/templates/admin/settings/settings_vcs.html:13 +msgid "Activate to set Kallithea to require SSL for pushing or pulling. If SSL certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 msgid "Show repository size after push" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:245 +#: kallithea/templates/admin/settings/settings_vcs.html:28 msgid "Log user push commands" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:249 +#: kallithea/templates/admin/settings/settings_vcs.html:32 msgid "Log user pull commands" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:253 -msgid "Advanced setup" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:258 +#: kallithea/templates/admin/settings/settings_vcs.html:36 +msgid "Update repository after push (hg update)" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:42 msgid "Mercurial Extensions" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:263 +#: kallithea/templates/admin/settings/settings_vcs.html:47 msgid "Enable largefiles extension" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:267 +#: kallithea/templates/admin/settings/settings_vcs.html:51 msgid "Enable hgsubversion extension" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:269 -msgid "Requires hgsubversion library installed. Allows cloning from svn remote locations" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:280 +#: kallithea/templates/admin/settings/settings_vcs.html:53 +msgid "Requires hgsubversion library to be installed. Allows cloning remote SVN repositories and migrates them to Mercurial type." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 msgid "Repositories location" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:285 -msgid "Click to unlock. You must restart RhodeCode in order to make this setting take effect." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:286 -#: rhodecode/templates/base/base.html:141 -msgid "Unlock" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:288 -msgid "Location where repositories are stored. After changing this value a restart, and rescan is required" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:312 -msgid "Test Email" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:320 -msgid "Email to" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:328 -msgid "Send" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:334 -msgid "System Info and Packages" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:337 -#: rhodecode/templates/changelog/changelog.html:51 -msgid "Show" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:5 -msgid "Add user" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:10 -#: rhodecode/templates/admin/users/user_edit.html:11 -#: rhodecode/templates/base/base.html:74 -msgid "Users" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:12 -#: rhodecode/templates/admin/users/users.html:23 -msgid "Add new user" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:50 -msgid "Password confirmation" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:5 -msgid "Edit user" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:13 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 -#, python-format -msgid "Edit %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:34 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:10 -msgid "Change your avatar at" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:35 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:11 -msgid "Using" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:43 -msgid "API key" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:50 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:21 -msgid "Current IP" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:70 -msgid "LDAP DN" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:79 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:45 -msgid "New password" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:54 -msgid "New password confirmation" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:163 -msgid "Email addresses" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:176 -#, python-format -msgid "Confirm to delete this email: %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:190 -msgid "New email address" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:5 -#: rhodecode/templates/base/base.html:252 -msgid "My account" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:9 -msgid "My Account" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:35 -msgid "My permissions" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:38 -#: rhodecode/templates/journal/journal.html:54 -msgid "My repos" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:41 -msgid "My pull requests" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:25 -msgid "API key - keep this in secret, change your password to generate new key" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:4 -msgid "Show closed pull requests" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:6 -msgid "Opened by me" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:17 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:45 -#: rhodecode/templates/pullrequests/pullrequest_data.html:11 -#: rhodecode/templates/pullrequests/pullrequest_show.html:26 -#: rhodecode/templates/pullrequests/pullrequest_show.html:42 -msgid "Closed" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:23 -msgid "Confirm to delete this pull request" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:30 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:51 -msgid "Nothing here yet" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:34 -msgid "I participate in" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:42 -#: rhodecode/templates/pullrequests/pullrequest_data.html:8 -#, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:5 -msgid "Users administration" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:9 -msgid "users" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:80 -msgid "Firstname" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:81 -msgid "Lastname" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:82 -msgid "Last login" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:5 +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "Click to unlock. You must restart Kallithea in order to make this setting take effect." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:72 +msgid "Filesystem location where repositories should be stored. After changing this value a restart and rescan of the repository folder are required." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:8 +msgid "General" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:13 +msgid "Use repository extra fields" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:15 +msgid "Allows storing additional customized fields per repository." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:30 +msgid "" +"Gravatar url allows you to use other avatar server application.\n" +" Following variables of the URL will be replaced accordingly.\n" +" {scheme} 'http' or 'https' sent from running Kallithea server,\n" +" {email} user email,\n" +" {md5email} md5 hash of the user email (like at gravatar.com),\n" +" {size} size of the image that is expected from the server application,\n" +" {netloc} network location/server host of running Kallithea server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:42 +msgid "" +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n" +" {scheme} 'http' or 'https' sent from running Kallithea server,\n" +" {user} current user username,\n" +" {netloc} network location/server host of running Kallithea server,\n" +" {repo} full repository name,\n" +" {repoid} ID of repository, can be used to contruct clone-by-id" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:54 +msgid "Dashboard items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:58 +msgid "Number of items displayed in the main page dashboard before pagination is shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:68 +msgid "Number of items displayed in the admin pages grids before pagination is shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:74 +msgid "Icons" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:79 +msgid "Show public repo icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:83 +msgid "Show private repo icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:91 +msgid "Meta-Tagging" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:110 +msgid "Parses meta tags from repository description field and turns them into colored tags." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 msgid "Add user group" msgstr "" -#: rhodecode/templates/admin/users_groups/users_group_add.html:10 -#: rhodecode/templates/admin/users_groups/users_groups.html:11 -#: rhodecode/templates/base/base.html:75 rhodecode/templates/base/base.html:92 +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 msgid "User groups" msgstr "" -#: rhodecode/templates/admin/users_groups/users_group_add.html:12 -#: rhodecode/templates/admin/users_groups/users_groups.html:26 -msgid "Add new user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 -msgid "Edit user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 -msgid "UserGroups" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 -#: rhodecode/templates/admin/users_groups/users_groups.html:38 +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 +#, python-format +msgid "%s user group settings" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 msgid "Members" msgstr "" -#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 -msgid "Chosen group members" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 -msgid "Remove all elements" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 -msgid "Available members" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 -msgid "Add all elements" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:109 -msgid "No members yet" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:117 -msgid "Global Permissions" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:5 -msgid "User groups administration" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:55 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 +#, python-format +msgid "User Group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 #, python-format msgid "Confirm to delete this user group: %s" msgstr "" -#: rhodecode/templates/admin/users_groups/users_groups.html:62 -msgid "There are no user groups yet" -msgstr "" - -#: rhodecode/templates/base/base.html:42 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 +msgid "Add user" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 +msgid "Users" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:53 +msgid "Password confirmation" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:5 +#, python-format +msgid "%s user settings" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 +#, python-format +msgid "This user is in an external Source of Record (%s); some details cannot be managed here." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 +msgid "New password confirmation" +msgstr "" + +#: kallithea/templates/admin/users/users.html:5 +msgid "Users administration" +msgstr "" + +#: kallithea/templates/admin/users/users.html:13 +msgid "users" +msgstr "" + +#: kallithea/templates/admin/users/users.html:54 +msgid "Firstname" +msgstr "" + +#: kallithea/templates/admin/users/users.html:55 +msgid "Lastname" +msgstr "" + +#: kallithea/templates/admin/users/users.html:56 +msgid "Last login" +msgstr "" + +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "" + +#: kallithea/templates/base/base.html:37 #, python-format msgid "Server instance: %s" msgstr "" -#: rhodecode/templates/base/base.html:53 -msgid "Report a bug" -msgstr "" - -#: rhodecode/templates/base/base.html:119 -#: rhodecode/templates/data_table/_dt_elements.html:9 -#: rhodecode/templates/data_table/_dt_elements.html:11 -#: rhodecode/templates/data_table/_dt_elements.html:13 -#: rhodecode/templates/summary/summary.html:8 +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 msgid "Summary" msgstr "" -#: rhodecode/templates/base/base.html:120 -#: rhodecode/templates/changelog/changelog.html:15 -#: rhodecode/templates/data_table/_dt_elements.html:17 -#: rhodecode/templates/data_table/_dt_elements.html:19 -#: rhodecode/templates/data_table/_dt_elements.html:21 +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 msgid "Changelog" msgstr "" -#: rhodecode/templates/base/base.html:121 -#: rhodecode/templates/data_table/_dt_elements.html:25 -#: rhodecode/templates/data_table/_dt_elements.html:27 -#: rhodecode/templates/data_table/_dt_elements.html:29 -#: rhodecode/templates/files/files.html:12 +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 msgid "Files" msgstr "" -#: rhodecode/templates/base/base.html:123 +#: kallithea/templates/base/base.html:149 msgid "Switch To" msgstr "" -#: rhodecode/templates/base/base.html:129 +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 msgid "Options" msgstr "" -#: rhodecode/templates/base/base.html:135 -#: rhodecode/templates/forks/forks_data.html:21 +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 msgid "Compare fork" msgstr "" -#: rhodecode/templates/base/base.html:137 -#: rhodecode/templates/base/base.html:310 -#: rhodecode/templates/search/search.html:14 -#: rhodecode/templates/search/search.html:54 +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 msgid "Search" msgstr "" -#: rhodecode/templates/base/base.html:143 +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "" + +#: kallithea/templates/base/base.html:176 msgid "Lock" msgstr "" -#: rhodecode/templates/base/base.html:151 +#: kallithea/templates/base/base.html:184 msgid "Follow" msgstr "" -#: rhodecode/templates/base/base.html:152 +#: kallithea/templates/base/base.html:185 msgid "Unfollow" msgstr "" -#: rhodecode/templates/base/base.html:155 -#: rhodecode/templates/data_table/_dt_elements.html:33 -#: rhodecode/templates/data_table/_dt_elements.html:35 -#: rhodecode/templates/data_table/_dt_elements.html:37 -#: rhodecode/templates/data_table/_dt_elements.html:74 -#: rhodecode/templates/forks/fork.html:9 +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 msgid "Fork" msgstr "" -#: rhodecode/templates/base/base.html:157 +#: kallithea/templates/base/base.html:190 msgid "Create Pull Request" msgstr "" -#: rhodecode/templates/base/base.html:163 +#: kallithea/templates/base/base.html:196 #, python-format msgid "Show Pull Requests for %s" msgstr "" -#: rhodecode/templates/base/base.html:163 -msgid "Pull Requests" -msgstr "" - -#: rhodecode/templates/base/base.html:200 +#: kallithea/templates/base/base.html:233 msgid "Not logged in" msgstr "" -#: rhodecode/templates/base/base.html:207 +#: kallithea/templates/base/base.html:240 msgid "Login to your account" msgstr "" -#: rhodecode/templates/base/base.html:230 +#: kallithea/templates/base/base.html:263 msgid "Forgot password ?" msgstr "" -#: rhodecode/templates/base/base.html:253 +#: kallithea/templates/base/base.html:286 msgid "Log Out" msgstr "" -#: rhodecode/templates/base/base.html:272 -msgid "Switch repository" -msgstr "" - -#: rhodecode/templates/base/base.html:284 +#: kallithea/templates/base/base.html:311 msgid "Show recent activity" msgstr "" -#: rhodecode/templates/base/base.html:285 -#: rhodecode/templates/journal/journal.html:4 +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 msgid "Journal" msgstr "" -#: rhodecode/templates/base/base.html:296 +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "" + +#: kallithea/templates/base/base.html:323 msgid "Show public gists" msgstr "" -#: rhodecode/templates/base/base.html:301 +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "" + +#: kallithea/templates/base/base.html:328 msgid "All public gists" msgstr "" -#: rhodecode/templates/base/base.html:303 +#: kallithea/templates/base/base.html:330 msgid "My public gists" msgstr "" -#: rhodecode/templates/base/base.html:304 +#: kallithea/templates/base/base.html:331 msgid "My private gists" msgstr "" -#: rhodecode/templates/base/base.html:309 +#: kallithea/templates/base/base.html:336 msgid "Search in repositories" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:14 -msgid "Inherit default permissions" -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:18 -#, python-format -msgid "Select to inherit permissions from %s settings. With this selected below options does not apply." -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:26 +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:19 +#, python-format +msgid "Select to inherit permissions from %s permissions settings, and default IP address whitelist." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:28 msgid "Create repositories" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:30 +#: kallithea/templates/base/default_perms_box.html:33 msgid "Select this option to allow repository creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:35 +#: kallithea/templates/base/default_perms_box.html:40 msgid "Create user groups" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:39 +#: kallithea/templates/base/default_perms_box.html:45 msgid "Select this option to allow user group creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:44 +#: kallithea/templates/base/default_perms_box.html:52 msgid "Fork repositories" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:48 +#: kallithea/templates/base/default_perms_box.html:57 msgid "Select this option to allow repository forking for this user" msgstr "" -#: rhodecode/templates/base/perms_summary.html:11 +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:22 msgid "No permissions defined yet" msgstr "" -#: rhodecode/templates/base/perms_summary.html:19 -#: rhodecode/templates/base/perms_summary.html:38 +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 msgid "Permission" msgstr "" -#: rhodecode/templates/base/perms_summary.html:20 -#: rhodecode/templates/base/perms_summary.html:39 +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 msgid "Edit Permission" msgstr "" -#: rhodecode/templates/base/root.html:44 +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 msgid "Add another comment" msgstr "" -#: rhodecode/templates/base/root.html:45 -#: rhodecode/templates/data_table/_dt_elements.html:147 +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 msgid "Stop following this repository" msgstr "" -#: rhodecode/templates/base/root.html:46 +#: kallithea/templates/base/root.html:47 msgid "Start following this repository" msgstr "" -#: rhodecode/templates/base/root.html:47 +#: kallithea/templates/base/root.html:48 msgid "Group" msgstr "" -#: rhodecode/templates/base/root.html:48 +#: kallithea/templates/base/root.html:49 msgid "members" msgstr "" -#: rhodecode/templates/base/root.html:49 -#: rhodecode/templates/pullrequests/pullrequest.html:203 +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 msgid "Loading ..." msgstr "" -#: rhodecode/templates/base/root.html:50 +#: kallithea/templates/base/root.html:51 msgid "loading ..." msgstr "" -#: rhodecode/templates/base/root.html:51 +#: kallithea/templates/base/root.html:52 msgid "Search truncated" msgstr "" -#: rhodecode/templates/base/root.html:52 +#: kallithea/templates/base/root.html:53 msgid "No matching files" msgstr "" -#: rhodecode/templates/base/root.html:53 -#: rhodecode/templates/changelog/changelog.html:45 -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:31 +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 msgid "Open new pull request" msgstr "" -#: rhodecode/templates/base/root.html:54 +#: kallithea/templates/base/root.html:55 msgid "Open new pull request for selected changesets" msgstr "" -#: rhodecode/templates/base/root.html:55 +#: kallithea/templates/base/root.html:56 msgid "Show selected changesets __S -> __E" msgstr "" -#: rhodecode/templates/base/root.html:56 +#: kallithea/templates/base/root.html:57 msgid "Show selected changeset __S" msgstr "" -#: rhodecode/templates/base/root.html:57 +#: kallithea/templates/base/root.html:58 msgid "Selection link" msgstr "" -#: rhodecode/templates/base/root.html:58 -#: rhodecode/templates/changeset/diff_block.html:8 +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 msgid "Collapse diff" msgstr "" -#: rhodecode/templates/base/root.html:59 +#: kallithea/templates/base/root.html:60 msgid "Expand diff" msgstr "" -#: rhodecode/templates/base/root.html:60 +#: kallithea/templates/base/root.html:61 msgid "Failed to revoke permission" msgstr "" -#: rhodecode/templates/base/root.html:61 +#: kallithea/templates/base/root.html:62 msgid "confirm to revoke permission for {0}: {1} ?" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:5 +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:5 #, python-format msgid "%s Bookmarks" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:26 -msgid "Compare bookmarks" -msgstr "" - -#: rhodecode/templates/bookmarks/bookmarks.html:51 -#: rhodecode/templates/bookmarks/bookmarks_data.html:8 -#: rhodecode/templates/branches/branches.html:50 -#: rhodecode/templates/branches/branches_data.html:8 -#: rhodecode/templates/changelog/changelog_summary_data.html:8 -#: rhodecode/templates/tags/tags.html:51 -#: rhodecode/templates/tags/tags_data.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 msgid "Author" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:52 -#: rhodecode/templates/bookmarks/bookmarks_data.html:9 -#: rhodecode/templates/branches/branches.html:51 -#: rhodecode/templates/branches/branches_data.html:9 -#: rhodecode/templates/changelog/changelog_summary_data.html:5 -#: rhodecode/templates/tags/tags.html:52 -#: rhodecode/templates/tags/tags_data.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 msgid "Revision" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:54 -#: rhodecode/templates/bookmarks/bookmarks_data.html:10 -#: rhodecode/templates/branches/branches.html:53 -#: rhodecode/templates/branches/branches_data.html:10 -#: rhodecode/templates/tags/tags.html:54 -#: rhodecode/templates/tags/tags_data.html:10 -msgid "Compare" -msgstr "" - -#: rhodecode/templates/branches/branches.html:5 +#: kallithea/templates/branches/branches.html:5 #, python-format msgid "%s Branches" msgstr "" -#: rhodecode/templates/branches/branches.html:26 -msgid "Compare branches" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:6 +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 #, python-format msgid "%s Changelog" msgstr "" -#: rhodecode/templates/changelog/changelog.html:19 +#: kallithea/templates/changelog/changelog.html:21 #, python-format msgid "showing %d out of %d revision" msgid_plural "showing %d out of %d revisions" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changelog/changelog.html:39 +#: kallithea/templates/changelog/changelog.html:43 msgid "Clear selection" msgstr "" -#: rhodecode/templates/changelog/changelog.html:42 -#: rhodecode/templates/forks/forks_data.html:19 +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 #, python-format msgid "Compare fork with %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:42 -msgid "Compare fork with parent" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:78 -#: rhodecode/templates/changelog/changelog_summary_data.html:28 +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 #, python-format msgid "" "Changeset status: %s\n" "Click to open associated pull request #%s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:82 -#: rhodecode/templates/compare/compare_cs.html:11 +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 #, python-format msgid "Changeset status: %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:104 -#: rhodecode/templates/summary/summary.html:403 -msgid "Show more" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:108 +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:114 msgid "Changeset has comments" msgstr "" -#: rhodecode/templates/changelog/changelog.html:117 -#: rhodecode/templates/changelog/changelog_summary_data.html:50 -#: rhodecode/templates/changeset/changeset.html:107 -#: rhodecode/templates/changeset/changeset_range.html:86 +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 #, python-format msgid "Bookmark %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:123 -#: rhodecode/templates/changelog/changelog_summary_data.html:56 -#: rhodecode/templates/changeset/changeset.html:113 -#: rhodecode/templates/changeset/changeset_range.html:92 +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 #, python-format msgid "Tag %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:128 -#: rhodecode/templates/changelog/changelog_summary_data.html:61 -#: rhodecode/templates/changeset/changeset.html:117 -#: rhodecode/templates/changeset/changeset_range.html:96 +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 #, python-format msgid "Branch %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:294 +#: kallithea/templates/changelog/changelog.html:299 msgid "There are no changes yet" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:4 -#: rhodecode/templates/changeset/changeset.html:91 +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 msgid "Removed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:5 -#: rhodecode/templates/changeset/changeset.html:92 +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 msgid "Changed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:6 -#: rhodecode/templates/changeset/changeset.html:93 +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 msgid "Added" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:8 -#: rhodecode/templates/changelog/changelog_details.html:9 -#: rhodecode/templates/changelog/changelog_details.html:10 -#: rhodecode/templates/changeset/changeset.html:95 -#: rhodecode/templates/changeset/changeset.html:96 -#: rhodecode/templates/changeset/changeset.html:97 +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 #, python-format msgid "Affected %s files" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:6 -#: rhodecode/templates/files/files_add.html:81 -#: rhodecode/templates/files/files_edit.html:64 +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 msgid "Commit message" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/changelog/changelog_summary_data.html:7 msgid "Age" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/changelog/changelog_summary_data.html:9 msgid "Refs" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:86 -msgid "Add or upload files directly via RhodeCode" -msgstr "" - -#: rhodecode/templates/changelog/changelog_summary_data.html:89 -#: rhodecode/templates/files/files_add.html:40 -#: rhodecode/templates/files/files_browser.html:31 -msgid "Add new file" -msgstr "" - -#: rhodecode/templates/changelog/changelog_summary_data.html:95 +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:95 msgid "Push new repo" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:103 +#: kallithea/templates/changelog/changelog_summary_data.html:103 msgid "Existing repository?" msgstr "" -#: rhodecode/templates/changeset/changeset.html:6 +#: kallithea/templates/changeset/changeset.html:6 #, python-format msgid "%s Changeset" msgstr "" -#: rhodecode/templates/changeset/changeset.html:39 -msgid "No parents" -msgstr "" - -#: rhodecode/templates/changeset/changeset.html:49 -msgid "No children" -msgstr "" - -#: rhodecode/templates/changeset/changeset.html:62 -#: rhodecode/templates/changeset/changeset_file_comment.html:41 -#: rhodecode/templates/changeset/changeset_range.html:44 +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 msgid "Changeset status" msgstr "" -#: rhodecode/templates/changeset/changeset.html:67 -#: rhodecode/templates/changeset/diff_block.html:23 -#: rhodecode/templates/files/diff_2way.html:46 +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 msgid "Raw diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:68 +#: kallithea/templates/changeset/changeset.html:58 msgid "Patch diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:69 -#: rhodecode/templates/changeset/diff_block.html:24 -#: rhodecode/templates/files/diff_2way.html:47 +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 msgid "Download diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:111 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:111 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "(%d inline)" msgid_plural "(%d inline)" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:103 -#: rhodecode/templates/changeset/changeset_range.html:82 +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 msgid "merge" msgstr "" -#: rhodecode/templates/changeset/changeset.html:126 -#: rhodecode/templates/compare/compare_diff.html:40 -#: rhodecode/templates/pullrequests/pullrequest_show.html:120 +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 #, python-format msgid "%s file changed" msgid_plural "%s files changed" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:128 -#: rhodecode/templates/compare/compare_diff.html:42 -#: rhodecode/templates/pullrequests/pullrequest_show.html:122 +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 #, python-format msgid "%s file changed with %s insertions and %s deletions" msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/pullrequests/pullrequest_show.html:138 -#: rhodecode/templates/pullrequests/pullrequest_show.html:202 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Showing a huge diff might take some time and resources" msgstr "" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:138 -#: rhodecode/templates/pullrequests/pullrequest_show.html:202 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Show full diff" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:23 +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 #, python-format msgid "Vote on pull request #%s" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:25 +#: kallithea/templates/changeset/changeset_file_comment.html:25 #, python-format msgid "Comment on pull request #%s" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:30 +#: kallithea/templates/changeset/changeset_file_comment.html:30 msgid "Status change on changeset" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:32 +#: kallithea/templates/changeset/changeset_file_comment.html:32 msgid "Comment on changeset" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:63 +#: kallithea/templates/changeset/changeset_file_comment.html:63 msgid "Submitting..." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:66 msgid "Commenting on line {1}." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:67 -#: rhodecode/templates/changeset/changeset_file_comment.html:153 +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 #, python-format msgid "Comments parsed using %s syntax with %s support." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:69 -#: rhodecode/templates/changeset/changeset_file_comment.html:155 -msgid "Use @username inside this text to send notification to this RhodeCode user" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:166 +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 msgid "Preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:80 -#: rhodecode/templates/changeset/changeset_file_comment.html:188 +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 msgid "Comment preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:88 -#: rhodecode/templates/changeset/changeset_file_comment.html:195 -#: rhodecode/templates/email_templates/changeset_comment.html:11 -#: rhodecode/templates/email_templates/pull_request_comment.html:16 +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 msgid "Comment" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:89 -msgid "Cancel" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:96 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "You need to be logged in to comment." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:96 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "Login now" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:100 +#: kallithea/templates/changeset/changeset_file_comment.html:100 msgid "Hide" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:159 +#: kallithea/templates/changeset/changeset_file_comment.html:159 msgid "Vote for pull request status" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:161 +#: kallithea/templates/changeset/changeset_file_comment.html:161 msgid "Change changeset status" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:178 +#: kallithea/templates/changeset/changeset_file_comment.html:179 msgid "Close (when approved or rejected)" msgstr "" -#: rhodecode/templates/changeset/changeset_range.html:5 +#: kallithea/templates/changeset/changeset_range.html:5 #, python-format msgid "%s Changesets" msgstr "" -#: rhodecode/templates/changeset/changeset_range.html:52 +#: kallithea/templates/changeset/changeset_range.html:59 msgid "Files affected" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:21 -#: rhodecode/templates/files/diff_2way.html:44 +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 msgid "Show full diff for this file" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:22 -#: rhodecode/templates/files/diff_2way.html:45 +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 msgid "Show full side-by-side diff for this file" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:30 +#: kallithea/templates/changeset/diff_block.html:38 msgid "Show inline comments" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:54 +#: kallithea/templates/changeset/diff_block.html:62 msgid "Show file at latest version in this repo" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:55 +#: kallithea/templates/changeset/diff_block.html:64 msgid "Show file at initial version in this repo" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:4 +#: kallithea/templates/compare/compare_cs.html:4 msgid "No changesets" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:32 +#: kallithea/templates/compare/compare_cs.html:8 msgid "Ancestor" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:5 +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 #, python-format msgid "%s Compare" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:9 +#: kallithea/templates/compare/compare_diff.html:16 msgid "Compare revisions" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:33 -#: rhodecode/templates/pullrequests/pullrequest_show.html:113 +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 #, python-format msgid "Showing %s commit" msgid_plural "Showing %s commits" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/compare/compare_diff.html:48 -#: rhodecode/templates/pullrequests/pullrequest_show.html:128 +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 msgid "No files" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:54 -#: rhodecode/templates/summary/summary.html:69 +#: kallithea/templates/data_table/_dt_elements.html:63 msgid "Mercurial repository" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:56 -#: rhodecode/templates/summary/summary.html:72 +#: kallithea/templates/data_table/_dt_elements.html:65 msgid "Git repository" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:74 -#, python-format -msgid "Fork of %s" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:88 +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:96 msgid "No changesets yet" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:95 -#: rhodecode/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 #, python-format msgid "Subscribe to %s rss feed" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:103 -#: rhodecode/templates/data_table/_dt_elements.html:105 +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 #, python-format msgid "Subscribe to %s atom feed" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.html:122 -#, python-format -msgid "Confirm to delete this repository: %s" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:137 -#, python-format -msgid "Confirm to delete this user: %s" -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:4 -#: rhodecode/templates/email_templates/pull_request.html:4 -#: rhodecode/templates/email_templates/pull_request_comment.html:4 -msgid "URL" -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:6 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:6 #, python-format msgid "%s commented on a %s changeset." msgstr "" -#: rhodecode/templates/email_templates/changeset_comment.html:9 +#: kallithea/templates/email_templates/changeset_comment.html:9 msgid "The changeset status was changed to" msgstr "" -#: rhodecode/templates/email_templates/main.html:8 -msgid "This is a notification from RhodeCode." -msgstr "" - -#: rhodecode/templates/email_templates/password_reset.html:4 +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:4 #, python-format msgid "Hello %s" msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:5 +#: kallithea/templates/email_templates/password_reset.html:5 msgid "We received a request to create a new password for your account." msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:6 +#: kallithea/templates/email_templates/password_reset.html:6 msgid "You can generate it by clicking following URL" msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:10 +#: kallithea/templates/email_templates/password_reset.html:10 msgid "Please ignore this email if you did not request a new password ." msgstr "" -#: rhodecode/templates/email_templates/pull_request.html:6 +#: kallithea/templates/email_templates/pull_request.html:6 #, python-format msgid "%s opened a pull request for repository %s and wants you to review changes." msgstr "" -#: rhodecode/templates/email_templates/pull_request.html:8 -#: rhodecode/templates/pullrequests/pullrequest.html:34 -#: rhodecode/templates/pullrequests/pullrequest_data.html:14 -#: rhodecode/templates/pullrequests/pullrequest_show.html:24 +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 msgid "Title" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:6 +#: kallithea/templates/email_templates/pull_request_comment.html:6 #, python-format msgid "%s commented on pull request \"%s\"" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:10 +#: kallithea/templates/email_templates/pull_request_comment.html:10 msgid "Pull request was closed with status" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:12 +#: kallithea/templates/email_templates/pull_request_comment.html:12 msgid "Pull request changed status" msgstr "" -#: rhodecode/templates/email_templates/registration.html:6 +#: kallithea/templates/email_templates/registration.html:6 msgid "View this user here" msgstr "" -#: rhodecode/templates/errors/error_document.html:55 +#: kallithea/templates/errors/error_document.html:47 #, python-format msgid "You will be redirected to %s in %s seconds" msgstr "" -#: rhodecode/templates/files/diff_2way.html:16 +#: kallithea/templates/files/diff_2way.html:15 #, python-format msgid "%s File side-by-side diff" msgstr "" -#: rhodecode/templates/files/diff_2way.html:20 -#: rhodecode/templates/files/file_diff.html:8 +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 msgid "File diff" msgstr "" -#: rhodecode/templates/files/diff_2way.html:48 +#: kallithea/templates/files/diff_2way.html:58 msgid "ignore white space" msgstr "" -#: rhodecode/templates/files/diff_2way.html:49 +#: kallithea/templates/files/diff_2way.html:59 msgid "turn on edit mode" msgstr "" -#: rhodecode/templates/files/file_diff.html:4 +#: kallithea/templates/files/file_diff.html:4 #, python-format msgid "%s File Diff" msgstr "" -#: rhodecode/templates/files/files.html:4 -#: rhodecode/templates/files/files.html:76 +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 #, python-format msgid "%s Files" msgstr "" -#: rhodecode/templates/files/files.html:30 -#: rhodecode/templates/files/files_add.html:33 -#: rhodecode/templates/files/files_edit.html:33 -msgid "Branch" -msgstr "" - -#: rhodecode/templates/files/files_add.html:4 +#: kallithea/templates/files/files_add.html:4 #, python-format msgid "%s Files Add" msgstr "" -#: rhodecode/templates/files/files_add.html:21 -msgid "Add file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:45 -msgid "File Name" -msgstr "" - -#: rhodecode/templates/files/files_add.html:49 -#: rhodecode/templates/files/files_add.html:58 -msgid "or" -msgstr "" - -#: rhodecode/templates/files/files_add.html:49 -#: rhodecode/templates/files/files_add.html:54 -msgid "Upload file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:58 -msgid "Create new file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:63 -#: rhodecode/templates/files/files_edit.html:39 -#: rhodecode/templates/files/files_ypjax.html:3 +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" +msgstr "" + +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 msgid "Location" msgstr "" -#: rhodecode/templates/files/files_add.html:67 -msgid "use / to separate directories" -msgstr "" - -#: rhodecode/templates/files/files_add.html:74 +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 +msgid "or" +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:58 msgid "New file mode" msgstr "" -#: rhodecode/templates/files/files_add.html:85 -#: rhodecode/templates/files/files_edit.html:68 +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 msgid "Commit changes" msgstr "" -#: rhodecode/templates/files/files_browser.html:13 -msgid "View" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:14 +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:14 msgid "Previous revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:16 +#: kallithea/templates/files/files_browser.html:16 msgid "Next revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:23 +#: kallithea/templates/files/files_browser.html:22 msgid "Follow current branch" msgstr "" -#: rhodecode/templates/files/files_browser.html:27 -msgid "Search file list" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:35 +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:29 msgid "Loading file list..." msgstr "" -#: rhodecode/templates/files/files_browser.html:48 +#: kallithea/templates/files/files_browser.html:42 msgid "Size" msgstr "" -#: rhodecode/templates/files/files_browser.html:49 +#: kallithea/templates/files/files_browser.html:43 msgid "Mimetype" msgstr "" -#: rhodecode/templates/files/files_browser.html:50 +#: kallithea/templates/files/files_browser.html:44 msgid "Last Revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:51 +#: kallithea/templates/files/files_browser.html:45 msgid "Last modified" msgstr "" -#: rhodecode/templates/files/files_browser.html:52 +#: kallithea/templates/files/files_browser.html:46 msgid "Last committer" msgstr "" -#: rhodecode/templates/files/files_edit.html:4 -#, python-format -msgid "%s Files Edit" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:21 +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:25 msgid "Edit file" msgstr "" -#: rhodecode/templates/files/files_edit.html:49 -#: rhodecode/templates/files/files_source.html:23 -msgid "Show annotation" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:51 -#: rhodecode/templates/files/files_source.html:26 -msgid "Download as raw" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:58 msgid "Source" msgstr "" -#: rhodecode/templates/files/files_edit.html:59 +#: kallithea/templates/files/files_edit.html:63 msgid "Editing file" msgstr "" -#: rhodecode/templates/files/files_history_box.html:2 -msgid "History" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:9 -msgid "Diff to revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:10 -msgid "Show at revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:11 -msgid "Show full history" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:16 +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 #, python-format msgid "%s author" msgid_plural "%s authors" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/files/files_source.html:6 -msgid "Load file history" -msgstr "" - -#: rhodecode/templates/files/files_source.html:21 -msgid "Show source" -msgstr "" - -#: rhodecode/templates/files/files_source.html:29 -#, python-format -msgid "Edit on branch:%s" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 -msgid "Edit on branch:?" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:8 +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:11 +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" +msgstr "" + +#: kallithea/templates/files/files_source.html:38 +#, python-format +msgid "Edit on Branch:%s" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "" + +#: kallithea/templates/files/files_source.html:44 msgid "Editing files allowed only when on branch head revision" msgstr "" -#: rhodecode/templates/files/files_source.html:46 +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:61 #, python-format msgid "Binary file (%s)" msgstr "" -#: rhodecode/templates/files/files_source.html:55 +#: kallithea/templates/files/files_source.html:71 msgid "File is too big to display" msgstr "" -#: rhodecode/templates/files/files_ypjax.html:5 +#: kallithea/templates/files/files_ypjax.html:5 msgid "annotation" msgstr "" -#: rhodecode/templates/files/files_ypjax.html:15 -msgid "Go back" -msgstr "" - -#: rhodecode/templates/files/files_ypjax.html:16 +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:24 msgid "No files at given path" msgstr "" -#: rhodecode/templates/followers/followers.html:5 +#: kallithea/templates/followers/followers.html:5 #, python-format msgid "%s Followers" msgstr "" -#: rhodecode/templates/followers/followers.html:9 -#: rhodecode/templates/summary/summary.html:183 -#: rhodecode/templates/summary/summary.html:184 +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 msgid "Followers" msgstr "" -#: rhodecode/templates/followers/followers_data.html:12 +#: kallithea/templates/followers/followers_data.html:12 msgid "Started following -" msgstr "" -#: rhodecode/templates/forks/fork.html:5 -#, python-format -msgid "%s Fork" -msgstr "" - -#: rhodecode/templates/forks/fork.html:28 +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:30 msgid "Fork name" msgstr "" -#: rhodecode/templates/forks/fork.html:65 +#: kallithea/templates/forks/fork.html:71 msgid "Private" msgstr "" -#: rhodecode/templates/forks/fork.html:74 +#: kallithea/templates/forks/fork.html:80 msgid "Copy permissions" msgstr "" -#: rhodecode/templates/forks/fork.html:78 +#: kallithea/templates/forks/fork.html:84 msgid "Copy permissions from forked repository" msgstr "" -#: rhodecode/templates/forks/fork.html:84 +#: kallithea/templates/forks/fork.html:90 msgid "Update after clone" msgstr "" -#: rhodecode/templates/forks/fork.html:88 +#: kallithea/templates/forks/fork.html:94 msgid "Checkout source after making a clone" msgstr "" -#: rhodecode/templates/forks/fork.html:93 -msgid "Fork this repository" -msgstr "" - -#: rhodecode/templates/forks/forks.html:5 +#: kallithea/templates/forks/fork.html:99 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 #, python-format msgid "%s Forks" msgstr "" -#: rhodecode/templates/forks/forks.html:9 -#: rhodecode/templates/summary/summary.html:189 -#: rhodecode/templates/summary/summary.html:190 +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 msgid "Forks" msgstr "" -#: rhodecode/templates/forks/forks_data.html:17 +#: kallithea/templates/forks/forks_data.html:17 msgid "Forked" msgstr "" -#: rhodecode/templates/forks/forks_data.html:42 +#: kallithea/templates/forks/forks_data.html:42 msgid "There are no forks yet" msgstr "" -#: rhodecode/templates/journal/journal.html:21 +#: kallithea/templates/journal/journal.html:24 msgid "ATOM journal feed" msgstr "" -#: rhodecode/templates/journal/journal.html:22 +#: kallithea/templates/journal/journal.html:25 msgid "RSS journal feed" msgstr "" -#: rhodecode/templates/journal/journal.html:32 -msgid "Refresh" -msgstr "" - -#: rhodecode/templates/journal/journal.html:35 -#: rhodecode/templates/journal/public_journal.html:24 -msgid "ATOM feed" -msgstr "" - -#: rhodecode/templates/journal/journal.html:51 -msgid "Watched" -msgstr "" - -#: rhodecode/templates/journal/journal_data.html:55 +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "" + +#: kallithea/templates/journal/journal_data.html:55 msgid "No entries yet" msgstr "" -#: rhodecode/templates/journal/public_journal.html:4 -#: rhodecode/templates/journal/public_journal.html:21 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 msgid "Public Journal" msgstr "" -#: rhodecode/templates/journal/public_journal.html:13 +#: kallithea/templates/journal/public_journal.html:16 msgid "ATOM public journal feed" msgstr "" -#: rhodecode/templates/journal/public_journal.html:14 +#: kallithea/templates/journal/public_journal.html:17 msgid "RSS public journal feed" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:4 -#: rhodecode/templates/pullrequests/pullrequest.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 msgid "New pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:25 -msgid "Create new pull request" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.html:47 +#: kallithea/templates/pullrequests/pullrequest.html:44 msgid "Write a short description on this pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:53 +#: kallithea/templates/pullrequests/pullrequest.html:50 msgid "Changeset flow" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:60 -#: rhodecode/templates/pullrequests/pullrequest_show.html:65 +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 msgid "Origin repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:85 -msgid "Send pull request" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.html:94 -#: rhodecode/templates/pullrequests/pullrequest_show.html:144 +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 msgid "Pull request reviewers" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:103 -#: rhodecode/templates/pullrequests/pullrequest_show.html:156 +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 msgid "owner" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:115 +#: kallithea/templates/pullrequests/pullrequest.html:114 msgid "Add reviewer to this pull request." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:129 +#: kallithea/templates/pullrequests/pullrequest.html:128 msgid "Detailed compare view" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:150 +#: kallithea/templates/pullrequests/pullrequest.html:149 msgid "Destination repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:4 +#: kallithea/templates/pullrequests/pullrequest_show.html:4 #, python-format msgid "%s Pull Request #%s" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:34 +#: kallithea/templates/pullrequests/pullrequest_show.html:36 msgid "Review status" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:39 -#: rhodecode/templates/pullrequests/pullrequest_show.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 msgid "Pull request status calculated from votes" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:56 msgid "Still not reviewed by" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:60 #, python-format msgid "%d reviewer" msgid_plural "%d reviewers" msgstr[0] "" msgstr[1] "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:62 msgid "Pull request was reviewed by all reviewers" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:79 -#: rhodecode/templates/pullrequests/pullrequest_show.html:81 +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 msgid "Pull changes" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:96 -msgid "Created on" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:109 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "reviewer" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:133 +msgid "Add or remove reviewer to this pull request." +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:137 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 msgid "Compare view" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:156 -msgid "reviewer" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:171 -msgid "Add or remove reviewer to this pull request." -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:175 -msgid "Save changes" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:4 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 #, python-format msgid "%s Pull Requests" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:9 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 #, python-format msgid "Pull requests from %s" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:11 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 #, python-format msgid "Pull requests to %s" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:42 -#, python-format -msgid "Instead, show pull requests to %s" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:44 -#, python-format -msgid "Instead, show pull requests from %s" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:50 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 msgid "Hide closed pull requests" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:52 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 msgid "Show closed pull requests too" msgstr "" -#: rhodecode/templates/search/search.html:6 -msgid "Search repository" -msgstr "" - -#: rhodecode/templates/search/search.html:8 -#: rhodecode/templates/search/search.html:16 +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 msgid "Search in all repositories" msgstr "" -#: rhodecode/templates/search/search.html:50 +#: kallithea/templates/search/search.html:53 msgid "Search term" msgstr "" -#: rhodecode/templates/search/search.html:62 +#: kallithea/templates/search/search.html:65 msgid "Search in" msgstr "" -#: rhodecode/templates/search/search.html:65 +#: kallithea/templates/search/search.html:68 msgid "File contents" msgstr "" -#: rhodecode/templates/search/search.html:66 +#: kallithea/templates/search/search.html:69 msgid "Commit messages" msgstr "" -#: rhodecode/templates/search/search.html:67 +#: kallithea/templates/search/search.html:70 msgid "File names" msgstr "" -#: rhodecode/templates/search/search_commit.html:35 -#: rhodecode/templates/search/search_content.html:21 -#: rhodecode/templates/search/search_path.html:15 +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 msgid "Permission denied" msgstr "" -#: rhodecode/templates/summary/summary.html:4 +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 +#, python-format +msgid "%s ATOM feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 +#, python-format +msgid "%s RSS feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "" + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "" + +#: kallithea/templates/summary/summary.html:4 #, python-format msgid "%s Summary" msgstr "" -#: rhodecode/templates/summary/summary.html:16 -#, python-format -msgid "%s ATOM feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:17 -#, python-format -msgid "%s RSS feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:62 +#: kallithea/templates/summary/summary.html:16 #, python-format msgid "Repository locked by %s" msgstr "" -#: rhodecode/templates/summary/summary.html:64 +#: kallithea/templates/summary/summary.html:18 msgid "Repository unlocked" msgstr "" -#: rhodecode/templates/summary/summary.html:83 -#, python-format -msgid "Non changable ID %s" -msgstr "" - -#: rhodecode/templates/summary/summary.html:88 -msgid "Public" -msgstr "" - -#: rhodecode/templates/summary/summary.html:88 -#: rhodecode/templates/summary/summary.html:89 -msgid "Fork of" -msgstr "" - -#: rhodecode/templates/summary/summary.html:97 -msgid "Remote clone" -msgstr "" - -#: rhodecode/templates/summary/summary.html:117 -msgid "Contact" -msgstr "" - -#: rhodecode/templates/summary/summary.html:131 +#: kallithea/templates/summary/summary.html:76 msgid "Clone url" msgstr "" -#: rhodecode/templates/summary/summary.html:136 +#: kallithea/templates/summary/summary.html:81 msgid "Show by Name" msgstr "" -#: rhodecode/templates/summary/summary.html:137 +#: kallithea/templates/summary/summary.html:82 msgid "Show by ID" msgstr "" -#: rhodecode/templates/summary/summary.html:143 +#: kallithea/templates/summary/summary.html:99 msgid "Trending files" msgstr "" -#: rhodecode/templates/summary/summary.html:151 -#: rhodecode/templates/summary/summary.html:167 -msgid "Enable" -msgstr "" - -#: rhodecode/templates/summary/summary.html:159 +#: kallithea/templates/summary/summary.html:115 msgid "Download" msgstr "" -#: rhodecode/templates/summary/summary.html:163 +#: kallithea/templates/summary/summary.html:119 msgid "There are no downloads yet" msgstr "" -#: rhodecode/templates/summary/summary.html:165 +#: kallithea/templates/summary/summary.html:121 msgid "Downloads are disabled for this repository" msgstr "" -#: rhodecode/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:127 msgid "Download as zip" msgstr "" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "Check this to download archive with subrepos" msgstr "" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "with subrepos" msgstr "" -#: rhodecode/templates/summary/summary.html:197 +#: kallithea/templates/summary/summary.html:163 msgid "Repository Size" msgstr "" -#: rhodecode/templates/summary/summary.html:204 -#: rhodecode/templates/summary/summary.html:206 +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 msgid "Feed" msgstr "" -#: rhodecode/templates/summary/summary.html:224 -msgid "Commit activity by day / author" -msgstr "" - -#: rhodecode/templates/summary/summary.html:232 -msgid "enable" -msgstr "" - -#: rhodecode/templates/summary/summary.html:235 -msgid "Stats gathered: " -msgstr "" - -#: rhodecode/templates/summary/summary.html:256 +#: kallithea/templates/summary/summary.html:193 msgid "Latest changes" msgstr "" -#: rhodecode/templates/summary/summary.html:258 +#: kallithea/templates/summary/summary.html:195 msgid "Quick start" msgstr "" -#: rhodecode/templates/summary/summary.html:272 -#, python-format -msgid "Readme file from revision %s" -msgstr "" - -#: rhodecode/templates/summary/summary.html:332 +#: kallithea/templates/summary/summary.html:209 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:299 #, python-format msgid "Download %s as %s" msgstr "" -#: rhodecode/templates/summary/summary.html:379 -msgid "files" -msgstr "" - -#: rhodecode/templates/summary/summary.html:689 -msgid "commits" -msgstr "" - -#: rhodecode/templates/summary/summary.html:690 -msgid "files added" -msgstr "" - -#: rhodecode/templates/summary/summary.html:691 -msgid "files changed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:692 -msgid "files removed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:694 -msgid "commit" -msgstr "" - -#: rhodecode/templates/summary/summary.html:695 -msgid "file added" -msgstr "" - -#: rhodecode/templates/summary/summary.html:696 -msgid "file changed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:697 -msgid "file removed" -msgstr "" - -#: rhodecode/templates/tags/tags.html:5 +#: kallithea/templates/tags/tags.html:5 #, python-format msgid "%s Tags" msgstr "" -#: rhodecode/templates/tags/tags.html:26 +#: kallithea/templates/tags/tags.html:29 msgid "Compare tags" msgstr "" diff --git a/rhodecode/i18n/pl/LC_MESSAGES/rhodecode.mo b/kallithea/i18n/pl/LC_MESSAGES/kallithea.mo rename from rhodecode/i18n/pl/LC_MESSAGES/rhodecode.mo rename to kallithea/i18n/pl/LC_MESSAGES/kallithea.mo index f578aa96a1cb1935b63960217c36569189859d29..db8285e2024c0b929736e1d2973ba592b97f1ce1 GIT binary patch literal 82851 zc%0n537k~L@drM5Ml|sxKjS$bE1^25>331e^q^}-!TWE=9mBf^XJ1(y}rAvtE;Q4 ztGi#>V!aDu^l#twVzKQAKC)9R^6%J@vDhXA=Mvn5;OPV#2`(eJGr_kA))V~ED8PLP zau#g_4<>jr!JiWRBf*~#e1+g<1XmHK;4> z;bRGINw9eg>XjUW@(TpFCwSr*;O|!iHzK%v4C?XV7}Vph1UDr3D!~m1zN6tEjzN3B zBDf>L&Bp?NgT?|cEn`t`JHa@?9)cYN7mY=J>y3-W#uMCx;Kc+F8;AD(Q{j)AP~RO1 z{tv-{O=!f5@^zcgj-tjtk>KWx?qVaARk9yxd9{71+JlgZZc=Y4P8gKInh!>xLe%fsU z+Q0V%gh}XJ5^N%PAk+P1jKAwAqutLD>`QRnW*Tz@_h?2si{Jo)XArF8erX0iUT;SF^$v~2 z_GCIZ6!8;>VmzO9DAFxI6yx^qha&$0QxHCV3i3H+3fh0|6x92cDQM>d3ST3*4Z*K9 z-qtNhw^Iw~X;cgFJE;ZuKcWS6nQsBzoJp`Bu}3SEd*BKd%*ZaEYe7L*c!xXvc#D2XQ@G zftPKkf<6zKiuz2MiuNR?qMgS~#kf6vD)4jNRM6$0G~FvxQLneBf)4+o?v17){g%^! zr=6!^JRC3$lz|C_#^46Zgk7;P0zx;5&8GiH9&greoZkJRSABc{Z86^zf0O|5w%h(UBNG8_YtyEoQ-g z=UIri?=0Z4X%_nZ&{?44pU*=1xmm!&xtjiZh08VGBeT$NZ)mDDOxMbeOV`U&cat zJr>5*0t!3qyaVBE||U>@j5pnm5QED^ja0er=i zz-L_&=>{ZG?lASAnneDyl4$?YNzm=tN!0g7g8Om*B{2{FD~WQy(C{DGz-u2H?buG; z4L15=Z}p#H18-e6=;JgS^2-v9_mg&v*S*_OpONjDm!`IZ-i~ia{TH;OeispJV0^Zt z-fwHVbyI+SQW#HtQwSfMQh6xPV~=;PSDW{ooN5t zooM%moxuC1U65P1>q7i}yMWgTUFi3YF7#7(7y9{_F7T82T^P5QcLDF$b)jFM>;nFu zC3rTMr|}ADq(32zemy;n^3GHLs|nsf@a8n|epEN`o9jkBPU}Yd&+bP2W!-4cAG#6$ zPu-x~7rN2@Roy6Ooeb)`Q3mzfHG_1!XV8y(W-vZRW`L&&8h%&?!ei!A? zKZ|py=N&oJ>pt~=P~ETPfS0#&S}%eNxL!H5bFK$Go$Vq2%RR*Vod>)v^+3lD61<4u zn*cFXM>J+A~>A!HyijmYc|^V>)GH#e^U2rvq4`Q6j6_z zi@?)>BI4~=MEc1^EjQLhc>pdH)HK|AAf(2s-W0G~tV059X_ zp#P@KL4O^k;ja4k%mIE+)$sGwefb=;`&!NS-Z`k>!;(r1HJGtrFVbQ9}C*CD8j^g}*GJ-q)2-{%s}T?_q*8wZ{HQa2Ubn9@PKb9-Vi3 z5dW?oifLH4|`DVy2qg2n;iqb@iT>!k3qZUAA|DGJqCEad>ui19Y)M65&iI}zb$ zo{08da3adP@+I-ATa9(v#3%e>e&9 z;0pw4=^5MWWYEDWCnNnrbzgTf(%*A3>iyu!$mcI7gYI8F8F=|j;fC{(|4-+G9tX}x zeuvHnJ`(eh{^LE@A^$u*AN}$1e8?G_o&x+1I|X=|b_(L3a0>YI zm8T&8$4^23ynG7!=i^h5&xQ*SzRLoPyFm+3-w_MYuI2@($Ill4|J@7FFY_1Zys`lK zUcLbRv}^(B_~8Yh!za}J4~_rt1)#SLPla4KCmGbcslx{sPKZ*QJuEM2G(Pb zo&mglbO!LV;hE@%pPh;N_dgTqMx2RuCeK8D=MWsn<(`RpzCv&;kJ~dLM;?3@=rnT{ z!cRO4__^#X;PZ~NQ16G-|DCgt?>c9LFYI_W!duTqy>e%RZcjcN^tR+|(E0MSQO~E( z2A)@)4Y_u!bI`6K=K!x$&Oy4P&p|s*JqP7ndJfV*sqx+;NK;kpN9Q8mN#}w-FFF_e zXUVy!|8*L^{9KHyCp6ys=YnoNBRGa&uk%z6I8WsObsu#e=&AEO(8FwnCuzKM&jZ~q zR{!6q|4jssCVB3j^FW6Ke~J3+_e(A3m%!(gU!uL;ztr`d#yeNx6~DxK^Oj$NAOAz$ z4Hv{>v?PypU4U`;&;_W+a~Gf=UcLbM`rixC?hP+QKksxQ@Ui!Wke9|?2))t-f+U*6 zj=2zc`PYR=|Mi8?d-S;o`H#5>bT|GYw0Gu3D6iupw4>)Dly}}mXwP*QfzRBo?iUrl za}nD2@kJO9>s_qtjf-`?aWUv>-;2SoS}z8@9CxwmZ7&8LF4OR*E>=Cx#lY_t3sJA_ z7J}Xy)jf3~@Rzd|q8}bu2s(XbA@ccjA;$M6mtb7fUxIdwy9D)4UxINt_Y%yz zza}`E;PaP&uk5%8uy^WUKTeXm6S?r|mPd(f4r$M7pLZl|k%=as-u z=}O@HxGRzV(kp@2%ddo-_uDIhkI%2fxcb==jO*Q&fW8MT0lkb`0=yr#MD;To?`RG0 zS%Q8#dkN}s$r6mi-)TP2ECIcIump7VqpOhar&j^byI%$QW6V{+=j^LMFK4Rzx~q`? zeOI9$AH53wvGvtRzt`2sf3mvMS0nwYS1TX58tIo^4L!&GR|D^#T#a$k_ZskrJ+A>j z`}sAfU;Y}@|I}-M=gTzw)@zX8BiEoF&s_uh`S=>(<;T|o{`6Y(`;OOwF2-Do`L~PU zX^gLH(VtuY7Uk^lTe$c7E&A(#-=hD95ImaT%-^D3kNy_@@%nGk?stC+x?2A_jH4Z{ zgB-gXL0aO*Qr98BSFb~UZ(fITdR-5?+wgkG;rm_>dOPEK%pbqM9`ebj*JJ->uiv4Z z*}sGP9D<_={^fVzGyih~(v4Jj;tjy}y*HqLKfVES+AcRj??3ZK;N{dCAz%LPM&$q8 zjTkroyb*l3-%Ut2=_d5+DK~)*m)r#Yay!8Z1fM5(D7X7&(D|I3(J%9E2AyAeGxA%0 zGy40Dn}PRDZUG*5x&`zy^cMI}yao7fQ}^s!P~S7u|0Z>>xCM0mp2AOWK|R-B3b^Z1 zq#wBy`5&h4)Kc`ru}jfE^Ok}hPg$z#i>08m->CaW4Zly*J+c&Z@Rz0N_ve>l9KXI4 z{qdptZ*wcs?R+cT4Y#7aeQw1(eZZ~Ar|DMRhq@JXdibs2BgbmG6K@55oTl#E72d1) z|M6B`w%-3t7Cqi~bkQ0_LjA)lRYL%ROAfq(3K8~Dkr+mKIA!{^+F zaW(%o;N|+;Fu&cS?#DI1*VX;rZD`k*x2YVl4E5P`8RBib4EgV}40!3k4Cxxwf7mjl zAH588HE9{>`mklF&zZ}Br-jRq|6+n9*2S*X^w(>7x2XG`WoXxmWvb^~rg{&}=aXf? z%a;n*xgF(fbUW(x)7z0xzuQr-Muq#`j`|J19qA6a9r+!4JLJM?n*RLTF+VNQ_^+t{ zySJnMUl8nM`n`i_l3?}@)c@l3^g9`*0@d!4s`kACg{dxY;tus0!M$nR1A zad%LtPcQ^X`iMvss=M=tmH`@P^##`?mjL$9aL3qD=!2kET2k|DT z|B?4V-srjq_&-PC#rFUYSKI@9-FT1c{q6z(efS>K_q}`2Pn+Hg|DWEA_UwHx`sL7j zkT&+PXz%6sf*;;{FZk{2_kvGt{s;Ki5u8eJEI~qD?6NVN%8%v*n2sr!g4(SMsgi2QbV5dF9BgE}4_)O;UAy*eJ$dFw&++q?(SZx=p@ z@puQphY9ZTN5KCj_&mY8{)Bn%f`?$QapOZ62OIra_r3lMdz=}6#(aO(pTWPL*6@uU z#&{g?FzBZ1Va&IS9>#clN@1@@AU6$o1p2t69)bU&Mqv+pt9s@plKL)zrPT>KMp$AG^(AHz8P<72?@ zOONTk;A0qVNLzDCe@rF&|v5;n!*Str~vc z|0ear_ zN$dyh@Femb^Caq>coO**opcZM=1-nNKc=2i{pnMnv!zdgeqVVC_51KCjGK-Bs&+Pi1s#u4 zcl%$l-+J0#fv=DLihlm`uV}|cPlNw&{WQky!B49^_B6&p+taAmqfhJn`84b`-d6wV z&!An_GbnG)GZ;^coKmS$K|59}?(|C`*3VQ!Q!#{r&^3Rs9p`H_7L;VhY4dXQRn(ED7Lp#rV4gLDN z*HGSLuL19`zJ`AK;5G1*FJDtTgxBHU=XJ!ddtK+D*Rf6<_d4=F?RDr;E`MF+@;8w0 zPH$*?-$41p)PJV>r`|w2N^hv0+#BeJNf&8$|yOhhlFdlyTzUu4V$G98zKKQ_q?*m^ay|4Q*?<4-@ z?_)l_QQc3ykN$b%eT<7OKhS-K4`8p+{{z)SD!k_djN26-p#L8I0ORVt4`8qH@dv=` zum6tv|NifY|M=g**Pc`V^;V&N+pI!A)vZFm4qXL4bLcA6uYDE9Sz#5*Ie!(#)n%*D zkH21p{Fkl*JuX-GpETZ+t1v#F(fEH`1%2JWSD`&W|4{k=he+prh<-WtL*VwE_PKA)kT+kS@h^`C)0Mtp|+CwvBeGF9Ur@fpT@ z;xn|XsPWFy^cQ}n`w^c3FSo1vuj+p7Gtk%9>c7e7(4%hsIozqwfp1UUCw&e&J?C?@ z`k+LQlM z&mVk=@pPfW-+hUCulN$}ed@e5H1q8h($ z+tRNv&i?cj@cfsrRFC%+`0YP6e9Nzq|Mp*_pZkA}dL8&R@;&5hlsofl;4$+x#^G_A z?#!=2mluBxes!zD=QaH|U+ezRH>mG+-vCd2zk%F0?i<~&`v&EAegpg*tMShNM&RdKc!412*F#YD6$vu^EhfnJ8mkEM{5!N)FBx|!f~=># zkRaprd4jwj@^^wfZ|uDeV2&X7+f4-JoC86olRvJ5bWf~<`n*Yy^~C=mDD(EZy`OW;Ylz${a zo)5a#Lpc`_WV!7Yf;`SYC&=rnUhBg>a((18etneRs_u4$?)t#v9D<@(Cdl&O5`srD zJ*|)W&)NX#3mX6*3pPOeFCobEd&LH5$4vxTZuo=7drjfT8=zeqY}iZaEKZQ=Zp4Pj z|F8{_Plh0m`?(vUeTxXP9I%Wa^M?-zGJS3RBj9()kI>)85M+LQB|(-$9wW&6BMX=YZbGx1~4Y zIlY0G<9Y)R^LqntO9=A#yPY7fGan~7oM4}g(ZAC+MtIxCh~Kj@=;X|eL5~+Iyn18w z>m3AneE)$U^O=V?Mmzqd>DJi<A17YaW{d4E*+){lXgb$`-Jy^hh1-*QptkW z8x-E9@&42Ybo`9^zuX6O`949m*Z4}qGh3rRg{@J)Q?>@4&QW;F*2wSatuemd+#2KS z-?;j*oCzcWWC+h1leAr*ET43);4HQdK;9V-v)R*WgE16@iyq6JGRkrunqY5 z-?jn&f1e=RYy50mjF(?*i+Go9i+)+QE%5Qqwy57fw?(brcF6b7+oAn`-41l|#&)2KO}7WVHEa)hZQUN_oUlFUY2o%5 zH+OB1_I|iM@V3DY7$1EI^7?J}9e{@!JD@%J9YDWJc0he!+yVK1vIFRA(;b1A`W?al zW-2^(N92Fmj^L};6CBC-+Y$V#F%G=s<7nTBakT3f>VJ70^!U3t`s=i^YF=)Y}tM)>YK zqurx+#`rp7XS6@RGx)}NJ0sl-I|E;z?F|0WxC`(m_>X`Z|n{ zIdv%i&vlrW->pNtM(hTD`des@=f9HtvggVW++r zr)_<~x92OouP@sFbzk6PyMDc7{Wr89@UTSTGX(D^xMBZZVz2S%{-B$kcSnD;?+!jO zdw0}x?(V4PFLprZK?sxV8{yyFVbh$}A+}jgm{ldQWz+0gn#M$~M}O|sp!I4%J&tccc^5RG->zstzF#!x{MV@SUnAV9M(~Go8Zi!+HzNJR z1X*A5Y$N#1<^xclF$0kP@ByITlLnx_em?;DJ*VNZfxTqCz577mf9gQAt8*ame8xb~ z=G%P;vc1NP zJyEYm_5>Y#uqXK5N9zBxz0l76_X6FFBFOd{r|yOPVte-zedKz3gHIf^H|lfn-jKs* z6J-1ShxZ2G+ISztZ`udpC+-7$JfrS!2=YE(%f8^BR}*AC(z6P;*bn1k;(oxx+53TC z+`b>;$M#2l1NR5tK5T#B;pF{64_E9D{`$iH=&y|q06!Xf0NQ!j0mvtL0OZqO9)NNF z>H)gm84NlYI#}iW!NBK5gOP6eV9@K|2ZL{{e<0{`uLIGq;}1l5TH*WyF@6^x2)g~l zfvEp02V&f9a1h4P<_95t-9c#2n1c{Mq3#n80^eSI5cu2*g1rd-JIo1zl{Nkag z*W#hT^EE?3FZXFa?+?Yi@VUnOW+>?XN5g>E0mF1%G7RG&F%0dPHw^uG#xUUdH^WfR zn}?x3cdPr)8vmJL$p6)0!1sH@P`@wLzt?cUjfaE2`wT}u&BIZ@BZectw&56W84b^= z|MA0tuQP_DzUL1IpSX57@UeV2@coFwr-q~6FKGIAhofHq8jgBxFaq`2WCZg4slpx9 zf432+*Fb{2f4a{Iq(5l{#_t8{et!h!k*`L8PPRO_m*`!0Ajo!QzdIP^?>7>3F>)l@ zl^luwIeH}0oiGyloiP&iyNqBgZe^13IxpVs=ImHqzk+Ay`g`$&+udzv@^&)rX5xts zE0eN4J0G|5@w$G+4m;D|s}VO_NT=gD`{;u0)rih<9XCVKOKzch6gO*gc*ZWSMSeLu z<#>5JM+uxve7u!TJNXXVsvg;+!l?$HXQk}wF^X0u?@872F6BMjDX+vXb^WrrSx&OQ zH#jbzc_*K?Ig6x0Md(w!lU7NAI6K@z&Oq_#b~1&$9elyl&Ez}$5Ai~E>|FR;0z5n6 zW|F~|c$RD{XCQfa+{^8@o#f9Et&=DEj)PsdtJ}(TNu+~wRwmJ5%lAm>__Uh}97F{X z2jaQiS&PYsK6AE}cQPreU)J@Uyqhbr_ZTN_$45Es?Y?7l(#iV{&q>-1ZKVc=@nk5P z=YPaUB$I(-l%2NoQs5Xjopyl-c4#Y_xyPpXJyzi-9#dLcd>l;is~b<{+(MQ*%j;-! ztz7j`YB{%3vS}gwCOYIRPi^<|P6GagZo;ZGztuuiE9DBnkTb4AzQfH0UlKDis4R}{ zkHW@^@CbeGT<7gj&$-=k;wNZQi5N|HJe#&H&yME`83~~b(@w(Tc2JjE#DwU- zn@id`RLVMj_ ziZ?XG1_=uq1kN)^S<5~?w;9pg6z{T$ISE_nq(~VnjiDhv*+Lt&uq>d>E#zY(65MP7 zvk7(FV4f!eE-V;0y5QvOcuUI!>BVfp>tGHcpA;{XYK%9vOK^heqn(jybANR^p2sn{ zdmN#KJk@~OHLkU_IX*g$4`E^~$wOeOsLA0dBgW}HYEj9xs5#5yR7nF!dArZEGBio_u#*6q%=eMZix z%6Cw!!(`uRA{Vl0*GlTZN)kE~`E)5h+pz*%OVnJnHMugzrJidnkwT)KF1`hWhJZ}j zX(#a;x4SJT%|nxto47VAU0GG0ud|`Z@nVOQx6{NwHI(tyK~obsiBRzyst&udG>!A< zwYwSpvuWnyy0o_wc5GoVg0I+!6d^sG=D%QmV@FeS+)5^ChvOkGVCpS>kyjwXaR|LWa=T z1;o?nrdq{nSiatM$9HU zXQ33AHLj2-M`ET$=zj6&b>esx~|m|2?o zA53$>di7wEwqlsk6-c<5;twvc+$RIVOHem+EUqOJ)kHf--Rw|PSjO<;4TN-y*Gh!U zgS9EKkrhlWgmr{^1c)rymErY;MRcB0VF42pEi8C-OvutG=z3WZ<%vV_v_gyaJgpoE zHTgW}nv^l-nG`aZ?C=c5f^>=X2X?xhORz*n8fj&zkyZ@L^SCAWraX;DpvhszSn!O$ zA#ioN#SC#c>h7|^*k~ef$^Oier6w0?y%P;AE82vzGC`FGSeJ$+)3_n>dD)nE-FTam z(gi8ik0yJ!y}e#$bk=6D&P!IPMD*FTRRUf`&#_iHH8wWJLK+wO6rL${hlU`eqzftz zks*$CVYC^#95w>)$PSy^&h_GY5(UV5gLx#aq>zzUXp_!DWUfHFtW204d8i}#v#8?{ z2_%UA+KF3`AR=+48W}q#i!mAwDprwO#59Z*!zo765}Q}NX&VbnbPcVnM8>wlt0}+N zJU7RUPuQ8H&~n5-X;%h-u{XvKcMI`ul6;u$648d2ui=$EwZk@Zht5^(W6N@b8qcj0 zW}~0PUHq>!e-Sl^x{);o!q~A2?3C3?f5b>C2-Yd=_9u7Kd(4exp$QV8!9-GR#?Op1 z_6wm-YIA5smGQIU-i(cO(`hTK6iTk{Zi^a5oJuH%*I_bsgPAwRCkq+^A0{9x?YW8{ zLKLmvi2sJ=UaD}O*g5xDFx}XYv_|R*Sz$!a9QLdndm5I-GS;|7)X2nH6B0jW(A-Aj z?6&dp1w@gm|XH!%4_uFv&(lVnltTA zt{X~upW~}1vkXjXGCs!gBECkL2*%*S)gy=)y1EF$DL8`PbKxoEJEw8%nk6~e)zu?R znYH2sHCtUy!GdBM`J!$1545hrR~VtfpziWh^np<**JrFQ+3^y zk)*yBB-`>T>-u~(F~FCj_05)4h|-B7yg){1ARCF;z%9`f z7j3Q{3Z#d^h(QbvyQLcC?r18Rd#h{@jZ}&XxC-<#BA3TT`TH>bmn!^5k%WmQTO)tl zu~DkXp;fi7OB4}>l|7j-7!r(XTK&%`R%8pUZC=7e!;3~s0FnE^m{GT*Y+7*&;T z)$msR$EY&?RN)bc2bFB7u%ymLLQ2LID=@!lae-yM_|d3em}GzY$-{V7V7TgqP2`rMR2st=v3UiPvg=gLL5*Y9cM^Xobt` zm0%v_O;BcXQ~Z+6LU@#$>B|co;-4hSnbp-W@&}dpAF}!7NppQU-HT7LiV=5@lMUP= z;~7_U0WMTo(dm9vf1N&>+X^iow?4Wd7gpRRNOsSd#fR!-uyhu2-cC01Hj2O2$l0hN z=gH)s5YZn6@upN`Oty;o2h3Bxngf-RxGT18#8-%1zNmP}U4sd2>{FA_IFKo*Ezm_o zmr5prpZWKpx6v#H;g@%|c?&{aB-ge(bKqdVY`zrknb8^U4h6wNO;(tqo{&vvVK9y5 zu{`6^k)pL6F$m#GtkcP$QV303xs;6tRff^b%schEbH_zuPK~#QdfML_;jK|5a1-n{ATKuKTVkZMW!;2|PwXO(cob$FbuchJRb@1XfZME4% zETWxEm>D!IehU9A3y(5J1VSq@ zvDbjnAkFIgw=CXw%heYeR})*bPaz`>-;iPrX^2%9Xm#b4r<%hIB{IT>k!MyWuc&fB zeP#BgZ->}CL8C%vm3@`%If{@|zTib1QN8&X2p7SkOZLjczGXV&*ci6k5PK_DH_LDr zmsC%_oInK`Xe$xKdHTB%Wf8zT9@e$Qm{3Bm70Yqz^-eH)CX>t)Se@%QMO7mshAw&9O0M z%dptkrdFy~9v>>$#Ky`}EFBZ6k$)nyFHf@KnReP~zMyu9i`DMRV>~C5knN1P5E&b| zK-z1Ji@re6XH+K;U0JhS*N>^Xe^|KXg}l}Zg?jWGR!qdkrrkEKs({EsuIjRHtQ$Yr zN^}u)Q#3e75I-r2kdtspgc_UE?UzC>4Vl!pk>f21h+!IqXlJ&a3-iau-tq7G4yp$gexOkI9lgd9SO(;4jEO-Y@NRiScquySb5O zo&Gi^G(|eyY$Pq#GOV|qlf~A8ZxLBZIX|Ed89PtBOKL%%MP?FamKdM~ zb-37)sMV1%Ed1m*zH?na5hP|YhwAU`Ov8ZnDkW+MhM&X|_K(j@@Tm-LER%1-q0r|Hy)azF4m%zrwZKq<3Y`&eLp=Vw|e!8E=Z% zIo=s&yE5LxATH1$OqdvZe1H_hOE0@5S()_BrF;kLn+h3|Q7*J~A9NTkuA8{I)G#M2 zMwgjbQ!{hj@Pe0o0^7W%1k037sSHid@Q!;~8qKk$Zr(ise#_P$!(vU;5Vo1MB35LU zXUrf}-x`Pr%ufB?ar7DQG38bJ(8if1f;~%Jck*tZ$N+7gD|#r=Do{E<4Fm;|mz;c~ zU#|+Q6VJB*mi60gIbFcZ*i2{m!$O9|8=(x!X)Q{&MUBY{oRLj&Al$2$J;O{%X9vcL)`VvcW4lIc+aymh z;7L?%LCRhvJunrOWF$HXn-R-;(Ka!_KSqAt~&BkkeoVP(Cp@xHae(2}*AK=Z-?4jSXPirz@Enh{h zs`RCC&5~X#b<5EOHxCo#Mn6_)86#Y!DcGceTFdC9BeGJ{YPNEkLK^MZA!-K|@INtz zrJ$U}#z}#HXt^JF8tG`fZD(bOiHd>8g_r{qlOowM4;`HqpE7#HsEMPYD&uOiN+YVq zARaQ_F7aR7tPCKZGNaI4WEzXyYxN*ik7j+=e#`Whi)RYh^QRo3-j^CB3Pc;G*qf@5p*0e| zD6gN7-FSM;qA*{WRx2n#V6BDCaX1FKvgkB)*g}L7eV&^Mq?-i+e%^g zoYim2&3&0h2G~TlGsF0_lHyWy>T<-SCM-@Adlhy}4ei5CR4bOi#%#3FqlP_0Jv7nI zTMeyNidVR?i9~B+$~RHZKR~WD=T3BW5^S+xn5!XsE-3&-69P z)e{-0d?{GAG1DTq6{HGlo!F_npfHeTkFde?L{)3YWW@3hQ+Eq2hX|olY+f87pkgQp zgGo9mhcfavU-?6~l;u0pLh%tjN|m@kTC!W8cqgH3$Lox+a$;dv1#Fr@ChlUeD6#HFd};k4(FQT z#$mFti&BnEE-4Wh*<}wlLr@IJyh6^mB9moJ0-JquY(R!I2_ck>TW(;uZQ;>4sbIK| z?1&qM9Ztf^(X`MhnN-e6vgFv#f;)Mc9ZpAdZpBRFnzQS+G`HY%H-HKnxS z+iMx?9lxxwwhLTMq&$)ynbc^JCBl2cO|za=4ZxZWLo**l*=&*5T$Q)^zA)-ZJDIL( ze*QGgn|xmisr1+vE4pO2bzj+|vy!=_loz$xtTU=yqxJ|=_@IKW;&E!1_@*=P7p zZb{_qdvnOPk%WdXwvuy6v>H=DY@#yD1jj4JsYbCnG=2+ckWq)Xaw;^QDBF1+dM9yuqN44|ZQ>-Fb z>=e5J%*tnWQ+xu;2ID#G>(e87T1olowpC|<)~EqooyX=kQ|xyB!L=R1hNkb6F#@u5 zK=dG`9Doe(mabi@?(%i1rpr}2!W9zhK7z2Sr;lzc8`^7R4=ezQhfa|$Qy@~@6zCZv zhs4zn=Bd#EkD#Q1A?*!J>x_S}1PKB|>LC-Y+D3h3?G|>xXiDWpJ=0btJman=P|i=) z4u&vOExc?-j)eJo!icXwE+W3=N9cHunpr(Fe6jsLP*uM$FOQ^^yJ&L3(WmO6MU`8E z&{F7=Hys%3mD>$0K&K-65)`LON`JS)VM*QgtzUT0m+KJhpkcF}nH29a!yX-TQ(SE5 z37;J#)cTo*3#+TKsaS497g*kehD5C>cBV#*Dtnm~k)r*fo)MoGrzg^e>Xcdv%%6Cr zqEj?0-YTMmiKn#smR1CUr+}bCOHF1>l_s*)GOB{C@~|IVhNMreX6X6nc&m6-#e)f} zQu~T(q*lXEOlTEuVuGsjlHghdYMJPoYYw<7iE7{=RY7XTKCuQ@D#;l{8l9OkqSX_1 zX=q_X0q}uz6!w=Um=+kb5Z!YtiQXuXG1WUw~k%^|T1f?)$M-_1#ODyn7Lq_R~3tJ0kmA8XTPFXa>{ zVOi12>_PSo%jQSyC1$n%c^N##KQpRkrtlE0YI7hjRrslh2Q872Dg6x!{{Wcu@@%ia zxr_u@<*hX_>WiEJ%)v+}bkenDqV81V%a`BaqE#Qhbhli-*&Kv=BXG1%Xz?96nK)Xg z6!|fie!<}@BU;$}!jf$fv*#vTKlxlC0fv@pjQ2HG8iNN6IEJ&HJKSvf4>*RqYi{3q zwn)(fE3&2W%t0uVKUwC|bIPKH3Z6?Mm>ZADFF^ zoEvW%6*VcXFE@x_Z8OsmXp8N^9inI0d;#DBIo_Ew9!@6ss@!G`f~tAbLZaLMCVVD@ zU$#KC7o1O3k22E(;oXtVTQe8?+gc*XuVrd8-L8G&(8lu`isqAp*p06^^j7CZ?;O!_ zUN4N)+?5ktoD{4)8Z~z??MxRrGfDZ09&{5QEN=3a*X3W6A^zE@_E4fBM7Cr#nM+mpm77Qx zWT%(y5VBRZQB>#1fd{8OH~|y$FWfL6b~}`3i4z!6!^{aVJrEjh03WZ@7ki)+*fqQwm2U z;g)wO^JP0@Viw+LQdLuRRSAMHBmuOFwT<~Z>o(Oh*rs8FMBF1Gw#*VP%pqAJBOV2F zX()GBomb`;xgw%PECcm&9HWUPUpKqjR+Q3Cdr7u?Q^aiTWUzfUIMz~VV-q1Y)gc#i z+%_ACChou%imWOv56O9+2?*c*9s<1RUQeiakX+Z zlF<&~Oq6c;*N!2FVXFoQOOS%>zN#8H>FSY6Sua*654}9M1($NfT8b96gqEO`Pb=|a zScx`e+TB>ImEu1}qujIG%EuSYJpsWv6|>_NYo(6~qee8tYK(7OqP{HTeY@w8lYFBr z-*6({pf^Iu5)!LmjUJ@;O{HlWJKIV#U!$(y*{lF|mXgb_V8Vuj?tqYB(<&EE@z$~G z6J&2uyp8-XJh5LJF{b{0O?h#yd?Sa!(jFh!u-Be!D9P7cOYB^K$;aP!ksWYF4=nR& z>J&vq$i6#Su(4&E=512e8OpUOjhdBS^%KbpCLFCn9(G1-gyfQLIj7=Vlk;uWj-CbL z9eTdi1@{^oOHraI8YO8AXTS1NJg<@IFXM);GGQx;Xprs}SB98PuUY}d>Ln89pQWt~ zf?*4JHwrCAg50WglZm;~TXypUUm*m&X+SR6)fG%*yg9guST7KeSi}_MG_Ktc-fzZ@ zJy0p|w3R_59Vg}jvhdX?=2(kAhRmgPH4=J-w$S0;8p*g85s3!f>`#P^el)Q`*S&SI z5(*zN=0o+ItEl?*76v{PWUgv9BO;h!zhO}3*X|9u(FnHt~xBtw3gXy`0Ps0 z=9i4FiB%n*bW?@(xUVA&EB|!!vpjmB)rYE&nG#qJ$*e`I6uE^;hN|e(WQ&^{6}t1D z&^~Qsi?QjJdzHiH+u=DP7+`V(d*o{Cq|2e*YDb9*%Z%d4R)&=cY&y#&3c0uMK!`+1 zxdFioQ37RYF{5L;ZVd7TKh2d}PM5JjCrf{{qKmcCVlBhBL&H9#mFD~^)FHdUl(n*vCI6HiY-PoREJ_<=Q>RSeKkh%O!cNeXJ3yQ z+-uF*$@vU+8cWO43I|CIl42`QzH-V>ZUkbp`QbiI>)}}3b)oAg zF@lOPKywdwFpx#CgPg#?8fYKM;u2X~ZL+19ESX!dhLVbyjGf?(0M1Wx^q zY@)CEvf>(PYF}F%SXhTXc`t&IWj0mIw<1C@Bb!lED^+D-zhEmR<``I>4J@aDrbwZ^7Pt!R!Hx&hFS6pj;RvwoCrnt9AY4l%m6(peIW z3f*>&dNgzvCpgsM)idQdZcI!5o3sHQ~<5_oX|qs3l0{EyyfpG$y{1?(|Kdu+)jlAW~w$_$9JnmR7SCB zyulMF=XjzcKV~MeX)f+sif-iS=8XhayYFzi*hME}(``|fIBeTt`7!*ds@yuz*Lvzm zYNQPM=2%ye<3r`Nz6jlRY}dF$*_SYJ)UHg6s=|HRP2u#I&YynJ5p%<1RKTTy}=XF`hI7+(d- zTM&ASmk3ET^~=F-=;DoPfdvB-8>bP1d$shIL4Pi8v!OhKD697YMN`}6x}xutwr^hE z(FxHT&a6B6zTD=5NRUF-nLKa2hNj(67Iq|yngQP{@9>3y-y@S`a3@x@r)T@aOwQES zjO#^42pG1}>iSkhYn3`;#2va-Qc`1OAQMaudOtqg&G8CduU1U>EsLb%%c)hxSQUw($o?q?Y{ZFbx=|ukF++kT%#jsudX+WxB1Q{|CxTx^0J?w{OR^CE1m z)?cxi6Y&(=5wV%rM>(S6$OVO%ho+9Gn4PMG`)n(Es$piJ42@j2b_D1=5)-?DN36-y z9K;I+3ipaSb%@RcbB<=JT8T1GRqwFBSzwi&tBB3Sy`a&A*$V63Dvd*=BXA^lCNG)T z#nECjy>bnEG=DGe%EMJPf^{g=@C0TePQ?uFjVJaLvw~ei=E7J7>-J}?%}N?u{1{|` z(AD2DiN<~3NT1zqGNwBzX8R;^0b(M26>PO@?T;BacQ9Y!93K`lTf@epqNzEiJJ1Bv z{AZ`Io|I;wM`J#pQT-PQ#4?0f8jh--8)M9nV`c$VE7}@5+dQtjgxmwqcdPh~J5QaLm70m?%D*<}=3?CIF>anZDs@vC0pcE{BWJ z(J^TLVi8?cg)AGxt04X(kpAJEpu!kXF+P4LKeCOPjJxuT0Dt*uRvYTYu<=m}?YEU5 zWb3dzbJgkU!n|1CXy;<`c$=$2kesM3Wcj|woeFKVj*`Z>?h8rZ zc%i4&^8BS9r*YWpH66K zN;XWx5_E7pm|%OeMPn}CFwsjn$%caqDX*c`9ULc_C*!4Ib~(JuL~igB-HmQ8)w_9e zYr{y@iZt-m%7f#34ji<1!@&I-2JRUjbim+&`!@{Sd*DEd*kCL;BJuWY7_?V>(B6ah z+Ix?I^shJHtkBS^g}S-Hgz{X1M5RIxv2Cx*i5~=y;aNG!($Ge-C*Nu`lu~9=1rk{r zT5YR)aJ<>2Wj*T|iTMp4FrZj0HcDHZc6$yd7?1@zyaCw(J`x6`HIo6^^nm`oo707y zm2MbAva&Zgp2>>S8?x7daeNNxml-l-P<&W?V4Q;M1`QlKWY73+yUFK4L-yv+e*8V~ zpg{xU#~v&G9A{vEN;8Pk?AgEf#HNX(gZ>!QII#CfY@;@?x_PkZ0tX1^I1s0p?EH{I zzP(}pARafX-Oe?P&LmvshlAt$w>kOVV|8Upy;&L@KbViH#|JhZ(712!n1lQ6S1e4} zouMahyIdB~+@iH|UcAT37acp7?BO$#)!xSqM<%|^w}Gsjw_<(*2~y;}VquRHFIIaw z*UP%y8HZE4@m9Bu;#Z62@+M|a>AUCOWAXDAdj>s1ZSap|pzL)*}}E(yaL_@6?#hO3-emM01i)(fSDSL}E|8 z3%PO;lUqRhmLHR2O=)QnP`=IaeIF$*dHE9cK{L%)g>D)?GWfmNX!f=9R1s=dLF=El zy9*43n-~Xc@^k)2PpRxPAafxE={f2r;8z~vU0cRtUN7#kD1pQA(>%PTW<|Sm<)Q@0 zN4`O8p-*l{yvL>Dnb&nQ@wl0i32{tN$q%zlnA8@bZjcfftez`Tk!U>ZT%yzJc7U&f zSIF>~bI4~+S^sx3@aF@2!aZ?ILu0Pl5f`KJx|B3k6SXD;1VwGby?&hZWOAaWh!iJ3%}39%d{47oc^^w zd#vs*Mt{B}uP`5+v$}|3_N1(|&HRqAjMtbk5e)J<|Db@4>$A+kqs%_1q$Uym3Sh1{ z3pG`ED8<5!CAy@Uv1Xao-)lymg_X-o`7Rz7U6y*KfU{5t zBaOo{h(b$XRh-nxMI04*WJK4Sb6CDV{tIm{=Ct0?h=_$HtFf5A=k$7AOdHTr& zxxstSqL?MV7Lb2L8EjQ~0eXgI5!3O6^N=HFtz6D*C2OYf$-LFZV^9!h#ikof248{1 z7xI%@m-x(sM>2zHPdG->3^U@Qr7mi#Fh7z|^QG=6i)>r5Fe#ak{IM|095QYBT}l`# z`op=PJxW8oJ5*GG*>DEDgyh;1(HP~@MQu&mDK}b}aNGDjRdvo5TaBh(-|#Xn+y1ai;aOXz#JxcvAu`S+U?dG$p7J(;L^O26j!;LM=07 zX#bzTbUjLk7L8D2J5r*8sah6K7ChxGR_|MexQR*$0-U%fun->Jl#*vMfHevDB0#4wy{z@HP}>KyocDAcO7>G?UV_(9rg1$!D>5& zm&_7BU%^3ZO)a$vl^BOJtV)x5B+=*l>u;g=}sGutJRR*EH~jj%Ocf_ZLxM5d4~bjBt*wyY~N!rDtT7%eFH^8R$&X?4*M;1yOP9GzFlE9O(=IzGNe z1D*Ppm7+ApEFdc*3Z&?e4d*~(5;+8eQsz~WP%V_Zh6lN4hzP32Uj?l&)Ldn6a%;>Y zYcm%moP=YitBme7Jk70{kbF$#7pU3l6Dw20iEl|XE>Q**R?g9AwX-Ydm5QqA0eK^A zyjeZj5q%ybk7%4%!EX3~g*o9BZhxiM;LusHGVeFeIXga{NIBzlLJOekW$K(j%hm=K z&nh@RD6Vylx6#<3@3vAto}>X}#eD^l6?fYbB4yRf(CWndYFX7jt~^7#Jke0 zj1k^m{@%Bd*lWlQ)F4sS_n@{c(8sicspcZU%lkG-3rc!jkVj}B>++l5s{V038mkGn zc8qQ!%g)LuW{RRHjq!;E&+&Q!6;ntb6^Oq|6ItG%fTBzuT=BKoMT$|P@!LoRxf$Y< zJ@Nrf8NU`jHJ1)!Zie)0XS^SwHoS3D5Cwyq%=Hu!?Ch^GnF2zeA$_~aDOf9jOq}W} zXyVthTxY467b+QN<#H{LSaN+(8D`L;!?W6WCx&&cR1{5d+-qfe`2YF~<31~jwLqs+ z@Rc8Bys8EkcniQyrqV39_*x-LlNFd`MDIuW$%Eqo>kD&18p}p-AT&`)-EM;BWl@Rq z#7dL5D=&H$y)5s6S{3h)&rodBXj6?(&@%ceu%OPjLi$@H-|OjdKRHi)MJJh-k(c#- zQ{f4JwXcu|Iq`LfoxxM+Yx@X!kO8?_ic}`+^Iwq$s=Y_v?E0v(;z@?nX=l4qloEak69T) zcU!7aSF9Hd57o8zf8?3;P*Wc|B?-uozjl`A9i9rhzsuOAWVfCp&!V;cVH$IW- zwyKH-L|QJSOx67>x5`(vC&b#QR)~zxAPX~k4x)W|mfc#bXW4!AWSGSM&mLx<&ht{B z6vg7rY&pWHBmo($KCB|r81-@ULVHl_&@#wuF=sWjQh%@(Z?>D9V`6uJUkJMR4A0Ru z-fc(3ycMRaV3TZZA8wxtrk1ayYZIa)ZT`wT*Wwj-RLZ$3R9H)kZK-_O!c+A(iE~-Hk`E?1aFbbb}QyYk+)$ z45@;I;45?pnk5<&s`USxFTXQ$VZg$>zWy%!W@@0`HKEn^f;CJ=PPKR7OL^ZKCSHs@ z0uQdHJVEtjga%nw`^%k3#6o#0f9W01m(tX0MZy5Bo>EEHLl&JLiYnO^*&eeCk`sG7 z@zlzBOjdRvcE?7Ga2gxIdy(<*>+#X|;+u&Tl}Q8B(US%mRff;jLWXqNz(9!BAtr$z z*N#nbd%PZ7w=cry+oK_@>5z?-wDf|>C?v0h*{Wl`t-O>yZ^3{LSODW5nY7O4f3=uz-w`WO?uk82Jru{4}3yLmKt+KO-a zl&i9FfeY`tls&e?>vTDJ7<$&i+-w%Pi#E+VSZMLYR4~~XYhndU%#mLhMHf2#52FL2 zxy9c!G-2{&e8S)2irhg-GQf1XEGv-pE#G`ZjZQ*miTM>)CuQf%bN4h^ajp?NPtkMP z{6>Zw#|g}Ob|?+Ih3EM7>TyII0E@nwooskzS*A?3Mt=n^i9iqSiUmrlc;znrG#2bOhvq;lLH%Z z&cNi&imS1Kmb=pOH?*TWgAZMfDO+8~_zDfVl8Zl#2sl=yR(auGR$?Nu%R#=@99w>4 zR7tRe1c$iwUI4zV${d8{V`5@>Dheyv*EBb_VYR^L>FWA1{r3;AC*%Mis?-=8>t9G8 zOu#g!j!nC5tjF^|BGyvT^?GOvdO9(I6$@hH-DG^M>!xUhJA&VSlgls7O+9iTQ?H%i z=Exq9tyckSl**^m*Z694&3|M3D=B7MIfn;@X9h4|Tos(v&!(*e?wO*ggyN@5-@j1* zigo(;U%q8s#7R6?AG~Aw1M=%m?qjl~Paee`27jS{%J~mmEKmQw@7?lZ7+@*;f{;`3Iz%VUk<=QIAZ(2) z#sT4E#GjZEvf7CpdaqPVJDX(`ctt?N*G{X29h;WNraO77Q?y83xl(6r9N*+p{i0}I zl~IY{PL^?}jC({_xj9aZQ_60k&(jpcuU?y%So!)vJ10j)<+e%>kFT?w&9|TpkP65p za3#sgq}O-4+6x(zQ7-g2a?qt-W9(qZ&9N*4%i?&k;?xmr45}Je6T@y|Bji{UpZsR^ z2gyM_YWT0-9|QnfahKO({g z%S$*;f08>oELud` zOLlkmfJ;pcY<-PNG-|*fRkH`tJ5_+>RfXA* zB-uD3$~A>{NPNqz&~XTgCK6pN;KCtoOXWTO%`6uXs}u1PsvfpKVud87%QwcSift3t zB~wO^7&URUG=~sHESuWIhw4d;qn5DEN+HpMU%^O8S1~YS@E0*qb@B;I;%mHplI+Uy zK^WMu>y`*rgEdxiE}qde-Y(%a;o#Qt3Gx8(!C6NyaU}&ky*p7zQS4>x>z^~g)mfD>z_-0H7p_2HZ5=t7$3udw6v6KV16=-Bi zQa-(5^dqsACtAru=Zb}*YD-WLEBnQn7+n{Z1+tS*k1|?W+MM7UBwL|ngdBlfxtx`D z#hz4p#lj@hkrQ55!km%fHa7avomh`$^qQP?^hVGbepvXsY^5*A1yM7C zV31eZT*jMuGR_jRnE`a0Q$2FLpxXHgJ$H~1g@F)`<(rgg1?;fFSa>@fXO@X-VZ^5# z$Hjh-9B$}gu4Zcl7l*V&xmCWu#eFr=HZKrFZmbM&998K1*1OTARJZTlYNb@a&KK(Q zrMhvx10gn1j|W0ZH}?zcnlIRFj696oxcXEj|01mNRD8CYd(*|IY>C)1x!Gbk$rk~L zUQvRBmRJ=@!@40ovMpu_<_rw{$_~beCu1CPZEO;5fUUTl3jy7@`X=w+I)YmSofO}g z6xcX>N08z^J($0jBelZ)V<@ zSFEE2S`K6kt+G{9t1MO)p>d0m8NJ7W7%q(1Etrd0F*!8bteP`%SY0f#PGX~KToy0l zvf#uE?&wF{@WCFT4<~l8-4ilHE|zG$kayKb(o~u;W1p6_e7xOTC4!{O^UTJ~{w^z- z!IpB|KY%93%-PI036?7u)`r~(g$}f=`yxtI zgoHQY&?9^(oLlRlTj4w2rA+dr=tMNh<$Gt8MRdz^ECutNx-MdQkzvlO3Cqc)k?SN{ zaOPDd>$gY5CSX8Rx&B)%a>}&wofa!}5H*!^k}UA^ja}^JWT2&WL@Qg&G_ESLzgvtuV3oq-?GRRzbY+>!03;HS>KxUhwiv`2~Z~x4wACLl(k(u3lfTlyzK! z7XG|v1f$t;;Mprrl&*pKAl6TYWk=b$dTLizi$8(yvLtl$RE7oej7n+zB4Bi88i$Cw zYr=1*VH_FZ&{eo$G+upwRO@s6VxMj>tWr<_sN9r8mcFD!sq|vFbI(G6L(>;h{`nT zi81OKHF&S#cnK_{ptVd3P3jlV=;P_E{&$nj3%bLT-+0W+RZUz+OFu)A>oU za=^5z`ma*VSXjoQrk2e{!V#5u#Xe_q@btSH0Ga3Cp^~7*G_J`A?=FcN1h*@i>m#w* z6S{ZRFE?bVjH7E#(iQ0nOG*~OU79@G%C1s?M9ro-Ean!yEZb&f`4qF9hHI==0NXm@ zwQM`-Kk^m$n1`d;tDU<$YJJ-5%YE2gD05e!&Oc-2=M#AO2Qf7lbALnV?E({06Z4@8 zl$mn{<|e@~Gj?NomcV!Vmd&Aau(8!#W;DIp9Wvnvn&Mtq4MAakXx|o&o z%)RNW&#_qQwo+_=l`rtkC_Q|)N@IL4(M7R6{1mzSs?(f@5vi%VrF-R-?L^V(L?LbY zO0d~3Uxr$}*5>vg|9%*nE;S!J=&9(G8r=CqL)d62Y@JObDyPr|UNt(s>eGBtUp!M5 zvH`4hBpTP6fPQ#_(3OF#d{o7qwGv${5E-}svSd%Gt;@j{U**L%y#2nKdu=#)id78l z#GB(-Mc?E}`TP`rjAR48754RqRBUpRSI!hBR>ESos`Ih`lFH!FEnfrl(k!-vmQ{?X z5(0C{sK25n!VyA-VzsY1_-?sWxd9=ZLCvZ*iK16_2viF(Sxz@aa52TiEaBnpPY&63qYFs$6C-RwuX@A2NYFqQaQ(u#=5`rqPP>feyp4Yuo;poh&J{TMZdquRdZBFT8sh zl9(&+c)?C>)IM7J4Wt*fo1Wq_d(TDh+=^14q408DXSfS|D^gz4s!%1?Ab#U&9J`6E z0bwK^!c9d9p%;!|d|s^bI7nnS6Q>(iTj1);(>uezQ*qVuk@Qs_5>k7g%EMi?41uB; zsu?NTswyR#`OcFVSpPYv`{fw_HO5WrTzlkflzsW{nI4kV0LV1yRP_a~R%I ziNpv6sJupbsEt>IyO|bN94v@r=L$yT#$FRWf{%m4sIM51;RSQ$t_1Xy5hhi3e#Y;t zXq}QZ+U{3&4Td1)rD(5B7m>X)?s;jf`SdoK`0NCCgBTxr(P#I}(|UNf#DCDKF+M_H z{~@U$bT59(v`JBeNx8V&N%6UKRj^P_!G$G!)k`B4EyfDrc`Sw*lJ`I{JyN6HEU%kp zh|Z+Y$*J_ISA8QH9o@ppq<&Cp&dbPqG!cI)-%!I5vj2= zv=rjw0dW_*v2ocL(~Mgtwl>T8d3*(r_KHhh-{mhg_>ph6XlrSi5I9;VwD=A@TQ-Bc zvnSTVuiW5n5>NfYim?{9BePf?>c1$!8zM9y3kmSqRAaoaF*h4LV8Ah4z}(@+c4@#d z+>>+r*0X7y-jg%i%6Wr-xM|ye*{)66MIYv^3)$f^*!&L|d3|3CuOCpfbPav9W1ZSi4l%@J!Gg%)Y;IjhGq3G`MO+rI=wl`zv)2c2gHdzSCE)#Lf*{yMg<$X6Fu{H^J- zi`&+mW6l>btp8M&g?vP8tvK;eJ?9oV9w>JZsIgJ_RIF+%B7WvdUc9WOR!MwAr+Mqx zx1-^U``R8@nveZHyX35B=g?Z6E zI7!?X+~dJXi}4Y`dqZ%`Q@9=+VsJjr@x(ZVFTSO@P4w7Ad%-D94QSTGP0i-mtEjOg z$iJS*&m_1#w|q}G{Oos~*D$nB>!Js6{R19qPr=C%A3dbda86 zG&x81V%f8&(8&$gy$duU?sV}*%H=nnl^~;m1%hCIW|VqrfTn>tU7wfjmHI|gW(U?FH8S1AXU%GfHw+~( zdd(5CiYT!g_IodU=YKW7su692b-SFT>V3<#PIDVgKIbMn__$V&n_t=> z0g4veCaC2Ejo}AcqP4Vak`P6xRMD4U`y&?nGxn*^t^Zf=x%bY@9g>pW1bv7ji5z|m zhcox1T34R$P;4G+6*XGo?tb&L&8Xz(v?&(Xj5v9p zqs|Pr02g$}H)`nRH#Mwzx&*uDbLPP-oKba%ABT*O2VnlD!M@<>oewN~+Tf-=-|R=78zuE{e|NTww^Ae zfPB!j*VxAtDKwJ<27ZksJZmn_)9roSwIw~^l{6WuyATPYBYU7ge|mFt9=nB6u}x+7 zqJ3aWP^~x#wQj`m+~p0A0>#`f>AD4S@J)49qv{a>F^-7%IHsd6_57^rHxZK}@g1GBW4F3Rl5Ww~vi>g}Oo3$A}alkRi6 z_!cpVW%k+gFFxnm`|Pna+B^-J%0Um&+S17~pehAy#`;l6D+}$vZuhukFoj5b$(>~?1 zQMH~>))wpGhG1e18{Ah4D1<6?Xy6O<<_x|?CWAH#RZU-PS!C{kr{+RD&aJaqGT2J9 zAj5~{*OpyMOrZkM=um(>(nm4i4TwHMciYW@qBYeyCSrso7n9Lk0-|{!!ySsdl*4fn zCa6zqTg$~*Lyx6kWVxlyA=(;euRN5s<3)*xA_$FQDrcr=Wq<;5_1{*Pn=FB7Ah6iU z1~EpCQdkD5Mc(9GfdSn>IgPE+@-v!9KUckvE+T>jX4@YoBCYjgU>Lbv8Zq-jHRDks zXGd><)WEb#Lv#Z^PN4w=(`+r2uU1?_I+7lNREuDZdHeEomVGPbNl^G{_jI#&ACO=L z2S?-+tb-;`mq_xIw|%zX)R)R}y3yKs>7)m06f^1cgM^A_7+^B#CMj@KYE4ENrbf(2 z{bSBGA$Yg;t9mKsHQmg*s5*KSs#%#B_3kxyIGtEZE>ozFvB>6q!*Irds0(8f0%yle zxqKib51=kRL7Lysq*w|LzSrwXLfx$_j0`T!9@$NgLKr-%^5E`rVO(HrN17y2gZlL) z&j0{36kI$;Mh0e_+C%!$MQl24`zDYD`(J&184Ii|BZ}lqko0DOw_D@q5ynI_5uWeq zMf^_wO+bZpY2x!9KPY=*8SJP>pAPb-f%Sr3jYFFvmqxOKP_G>UR5qTUFO(SM;=&3(=#|?% zAx0Qvf#*kqy$27f<@O;}{3=dLavV@ZlNY#2m7>=9vCG6&)+UYk_2knsG6{OFG^jb{ zuqDY+9YQ-mFiF1)Bt267H83z6Om^;Vu|aU5G$Elj0+iWs57}Zi1&dr0Ii8EgGowlaUn}Ij zU1%JMaJesVd|zKO$Ns2ZkGbpJTN;}A4Nc!H#Yk&fl^g!rDv))G>+v;qs=Z)Qq62^m zT%iPz4E$@Fjr&^~rFZ|k?JZivWMmQq7fWSWfaJ`*EB-+p($*Vr=8)rAL~g1`O{D;S zrBWpiM1VJf?jIyFG{Z;^wgA={>9*LW)5y&2c7Stw3SZ8sU#lA(=EOJk>87AE!LzQYKlE7|o-H!H{h zQ}a&-3=IaRj^A-ciaA>7rb}vfed2zsJ5FK>7EmZzqvsOiDVK$?6A9W~nNa!cfo-x_ zdPKWwpJtw2vc4=93Ag0;{@tM~kIlwo7}v?zSeb1YV~7F;xEXLD=$O$+df-9-{*xPy z_fJ12=%0*DuoUbqo6SN0NR68V`$y8gv@k0O*ObMlH2pS+&jiWZR0K>Aj4F$+q$@_CqFXsruWt(6imKL!q4kiZQi53q9Ebn~x`~RuyN)MP02j4)7lUZ#%q}(!F~*Q?fZiQ4~hr4^LM=um0tX{-0FE49)E4$W$jaA zsXyY*+n%Ogyb$6q3^Y+M2JD~iJkY0JJZwWi?^`13xHsLidDr6abml2bnXcDsVvf%5 z$+(9bgfN#n!RQ2~du%MV+=2FrC=nFNs=gRiDV}SP^&)fUVH8QH)3c%rXO=>b7Ux5x z?f1FZKr9+I-e}*nqg#hvnruAOuX&QH-dZosG^_a}U#=2H z3dNTRyI9%0;-?1Ollp(_xV}LUfbuztzVp|ZY-1xx{z`*FzeFi``5xW_M~2sS<0=ko zxBJ3XQyh($Xf2SLYtQgVg+Nk+!pQTtGgm4hmnPFWM6(m6b^26RFf&_Fn_gW>7EUS) z9zP)$ihMj&Oth{#MwT?(s?$Gy6|C!2B-Q!Al4}{CRai|&PP{Uhl#G0Gfd2T^X=y^X zEgOeS3y5x*<A4_#LNDE(Oq9D1G+HJxqZ6o2>9CB43T{YBrJazLxjnNe_$nY% zP~t|Oh7)PZkVJQ$@yP%0U+BUC_%C%CEXBQ~X%&Cfy#J^zLZZ@N7}KuA)&RtR7twQ=#c)hw^4F4QfmB8WY^GE)ShB z74wS~0|VY_3zNbudoK?t6<0)zq7(Iu1eMHrJwpce_XJbQ2ZmBytgUNpC;fABeM$sE XcS, 2013 # FIRST AUTHOR , 2010 @@ -9,1027 +9,1145 @@ # Nemcio , 2012-2013 msgid "" msgstr "" -"Project-Id-Version: RhodeCode\n" -"Report-Msgid-Bugs-To: marcin@maq.io\n" -"POT-Creation-Date: 2013-06-05 19:55+0200\n" -"PO-Revision-Date: 2013-06-07 16:50+0000\n" -"Last-Translator: Nemcio \n" -"Language-Team: Polish (http://www.transifex.com/projects/p/RhodeCode/language/pl/)\n" +"Project-Id-Version: Kallithea\n" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" +"PO-Revision-Date: 2014-02-13 14:34+0000\n" +"Last-Translator: marcinkuzminski \n" +"Language-Team: Polish " +"(http://www.transifex.com/projects/p/Kallithea/language/pl/)\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && " +"(n%100<10 || n%100>=20) ? 1 : 2)\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -"Language: pl\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: rhodecode/controllers/changelog.py:149 + +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 +msgid "There are no changesets yet" +msgstr "Brak zestawienia zmian" + +#: kallithea/controllers/changelog.py:186 msgid "All Branches" msgstr "Wszystkie gałęzie" -#: rhodecode/controllers/changeset.py:84 +#: kallithea/controllers/changelog.py:189 +msgid "(closed)" +msgstr "(zamknięty)" + +#: kallithea/controllers/changeset.py:87 msgid "Show white space" msgstr "pokazuj spacje" -#: rhodecode/controllers/changeset.py:91 rhodecode/controllers/changeset.py:98 +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 msgid "Ignore white space" msgstr "Ignoruj pokazywanie spacji" -#: rhodecode/controllers/changeset.py:164 -#, python-format -msgid "%s line context" -msgstr "%s linia w kontekście" - -#: rhodecode/controllers/changeset.py:345 -#: rhodecode/controllers/pullrequests.py:478 +#: kallithea/controllers/changeset.py:167 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 #, python-format msgid "Status change -> %s" msgstr "Zmiana statusu -> %s" -#: rhodecode/controllers/changeset.py:376 +#: kallithea/controllers/changeset.py:386 msgid "" -"Changing status on a changeset associated with a closed pull request is not " -"allowed" -msgstr "Zmiana statusu na grupy zmian powiązania łączy zamkniętego wniosku jest niedozwolona" - -#: rhodecode/controllers/compare.py:74 -#: rhodecode/controllers/pullrequests.py:256 -msgid "There are no changesets yet" -msgstr "Brak zestawienia zmian" - -#: rhodecode/controllers/error.py:69 +"Changing status on a changeset associated with a closed pull request is " +"not allowed" +msgstr "" +"Zmiana statusu na grupy zmian powiązania łączy zamkniętego wniosku jest " +"niedozwolona" + +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +msgid "Select changeset" +msgstr "Wybrane zmiany" + +#: kallithea/controllers/error.py:72 msgid "Home page" msgstr "Strona główna" -#: rhodecode/controllers/error.py:98 -msgid "" -"The request could not be understood by the server due to malformed syntax." -msgstr "Wniosek nie może być rozumiany przez serwer z powodu zniekształconej składni." - -#: rhodecode/controllers/error.py:101 +#: kallithea/controllers/error.py:101 +msgid "The request could not be understood by the server due to malformed syntax." +msgstr "" +"Wniosek nie może być rozumiany przez serwer z powodu zniekształconej " +"składni." + +#: kallithea/controllers/error.py:104 msgid "Unauthorized access to resource" msgstr "Nieautoryzowany dostęp do zasobów" -#: rhodecode/controllers/error.py:103 +#: kallithea/controllers/error.py:106 msgid "You don't have permission to view this page" msgstr "Nie masz uprawnień do przeglądania tej strony" -#: rhodecode/controllers/error.py:105 +#: kallithea/controllers/error.py:108 msgid "The resource could not be found" msgstr "Zasób nie został znaleziony" -#: rhodecode/controllers/error.py:107 +#: kallithea/controllers/error.py:110 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." -msgstr "Serwer napotkał niespodziewany warunek, który uniemożliwia jej spełnienie żądania." - -#: rhodecode/controllers/feed.py:52 +msgstr "" +"Serwer napotkał niespodziewany warunek, który uniemożliwia jej spełnienie" +" żądania." + +#: kallithea/controllers/feed.py:55 #, python-format msgid "Changes on %s repository" msgstr "Zmiany w %s repozytorium" -#: rhodecode/controllers/feed.py:53 +#: kallithea/controllers/feed.py:56 #, python-format msgid "%s %s feed" msgstr "%s %s zasilać" -#: rhodecode/controllers/feed.py:86 -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Changeset was too big and was cut off..." msgstr "Lista zmian była zbyt duża i została ucięta..." -#: rhodecode/controllers/feed.py:90 +#: kallithea/controllers/feed.py:93 #, python-format msgid "%s committed on %s" msgstr "%s zakomitowal w %s" -#: rhodecode/controllers/files.py:89 +#: kallithea/controllers/files.py:92 msgid "Click here to add new file" msgstr "Kliknij tutaj, by dodać nowy plik" -#: rhodecode/controllers/files.py:90 -#, python-format -msgid "There are no files yet %s" -msgstr "Brak plików %s" - -#: rhodecode/controllers/files.py:271 rhodecode/controllers/files.py:339 +#: kallithea/controllers/files.py:93 +#, python-format +msgid "There are no files yet. %s" +msgstr "" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 #, python-format msgid "This repository is has been locked by %s on %s" msgstr "Repozytorium zostało zablokowane przez %s na %s" -#: rhodecode/controllers/files.py:283 +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:346 +#, python-format +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "Wystąpił błąd w trakcie zatwierdzania" + +#: kallithea/controllers/files.py:373 msgid "You can only edit files with revision being a valid branch " msgstr "Można tylko edytować pliki z rewizji obecnej gałęzi" -#: rhodecode/controllers/files.py:297 -#, python-format -msgid "Edited file %s via RhodeCode" -msgstr "Edytowanie %s w RhodeCode" - -#: rhodecode/controllers/files.py:313 +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "Edytowanie %s w Kallithea" + +#: kallithea/controllers/files.py:403 msgid "No changes" msgstr "Bez zmian" -#: rhodecode/controllers/files.py:322 rhodecode/controllers/files.py:394 +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 #, python-format msgid "Successfully committed to %s" msgstr "Committ wykonany do %s" -#: rhodecode/controllers/files.py:327 rhodecode/controllers/files.py:405 -msgid "Error occurred during commit" -msgstr "Wystąpił błąd w trakcie zatwierdzania" - -#: rhodecode/controllers/files.py:351 -msgid "Added file via RhodeCode" -msgstr "Dodano %s poprzez RhodeCode" - -#: rhodecode/controllers/files.py:368 +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "Dodano %s poprzez Kallithea" + +#: kallithea/controllers/files.py:461 msgid "No content" msgstr "Brak treści" -#: rhodecode/controllers/files.py:372 +#: kallithea/controllers/files.py:465 msgid "No filename" msgstr "Brak nazwy pliku" -#: rhodecode/controllers/files.py:397 +#: kallithea/controllers/files.py:490 msgid "Location must be relative path and must not contain .. in path" msgstr "Lokalizacja musi być ścieżką względną i nie może zawierać .. ścieżki" -#: rhodecode/controllers/files.py:431 +#: kallithea/controllers/files.py:524 msgid "Downloads disabled" msgstr "Pobieranie wyłączone" -#: rhodecode/controllers/files.py:442 +#: kallithea/controllers/files.py:535 #, python-format msgid "Unknown revision %s" msgstr "Nieznana wersja %s" -#: rhodecode/controllers/files.py:444 +#: kallithea/controllers/files.py:537 msgid "Empty repository" msgstr "Puste repozytorium" -#: rhodecode/controllers/files.py:446 +#: kallithea/controllers/files.py:539 msgid "Unknown archive type" msgstr "Nieznany typ archiwum" -#: rhodecode/controllers/files.py:631 -#: rhodecode/templates/changeset/changeset_range.html:9 -#: rhodecode/templates/email_templates/pull_request.html:12 -#: rhodecode/templates/pullrequests/pullrequest.html:124 +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 msgid "Changesets" msgstr "Różnice" -#: rhodecode/controllers/files.py:632 -#: rhodecode/controllers/pullrequests.py:149 -#: rhodecode/controllers/summary.py:76 rhodecode/model/scm.py:682 -#: rhodecode/templates/switch_to_list.html:3 -#: rhodecode/templates/branches/branches.html:10 +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 msgid "Branches" msgstr "Gałęzie" -#: rhodecode/controllers/files.py:633 -#: rhodecode/controllers/pullrequests.py:150 -#: rhodecode/controllers/summary.py:77 rhodecode/model/scm.py:693 -#: rhodecode/templates/switch_to_list.html:15 -#: rhodecode/templates/tags/tags.html:10 +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 msgid "Tags" msgstr "Etykiety" -#: rhodecode/controllers/forks.py:176 -#, python-format -msgid "Forked repository %s as %s" -msgstr "Gałęzi %s w repozytorium %s" - -#: rhodecode/controllers/forks.py:190 +#: kallithea/controllers/forks.py:191 #, python-format msgid "An error occurred during repository forking %s" msgstr "Wystąpił błąd podczas rozgałęzienia %s repozytorium" -#: rhodecode/controllers/journal.py:110 rhodecode/controllers/journal.py:153 +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "Repozytoria" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "gałąź" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "Tag" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "Bookmark" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 msgid "public journal" msgstr "Dziennik publiczny" -#: rhodecode/controllers/journal.py:114 rhodecode/controllers/journal.py:157 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 msgid "journal" msgstr "dziennik" -#: rhodecode/controllers/login.py:138 -msgid "You have successfully registered into RhodeCode" +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" msgstr "Udało Ci się zarejestrować na stronie" -#: rhodecode/controllers/login.py:159 +#: kallithea/controllers/login.py:237 msgid "Your password reset link was sent" msgstr "Twój link zresetowania hasła został wysłany" -#: rhodecode/controllers/login.py:179 +#: kallithea/controllers/login.py:257 msgid "" -"Your password reset was successful, new password has been sent to your email" +"Your password reset was successful, new password has been sent to your " +"email" msgstr "Twoje hasło zostało zresetowane, nowe hasło zostanie wysłane na e-mail" -#: rhodecode/controllers/pullrequests.py:136 -#: rhodecode/templates/changeset/changeset.html:10 -#: rhodecode/templates/email_templates/changeset_comment.html:8 +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 msgid "Changeset" msgstr "Grupy zmian" -#: rhodecode/controllers/pullrequests.py:146 +#: kallithea/controllers/pullrequests.py:157 msgid "Special" msgstr "Specjalne" -#: rhodecode/controllers/pullrequests.py:147 +#: kallithea/controllers/pullrequests.py:158 msgid "Peer branches" msgstr "gałęzie" -#: rhodecode/controllers/pullrequests.py:148 rhodecode/model/scm.py:688 -#: rhodecode/templates/switch_to_list.html:28 -#: rhodecode/templates/bookmarks/bookmarks.html:10 +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 msgid "Bookmarks" msgstr "Zakładki" -#: rhodecode/controllers/pullrequests.py:321 +#: kallithea/controllers/pullrequests.py:330 msgid "Pull request requires a title with min. 3 chars" msgstr "Wniosek połączenia gałęzi wymaga tytułu z min. 3 znakami" -#: rhodecode/controllers/pullrequests.py:323 -msgid "Error creating pull request" -msgstr "Błąd podczas tworzenia prośby o łączenie gałęzi" - -#: rhodecode/controllers/pullrequests.py:343 +#: kallithea/controllers/pullrequests.py:332 +#, python-format +msgid "Error creating pull request: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:354 msgid "Successfully opened new pull request" msgstr "Prośba o wykonanie połączenia gałęzi została wykonana prawidłowo" -#: rhodecode/controllers/pullrequests.py:346 +#: kallithea/controllers/pullrequests.py:357 msgid "Error occurred during sending pull request" msgstr "Wystąpił błąd podczas prośby o połączenie gałęzi" -#: rhodecode/controllers/pullrequests.py:385 +#: kallithea/controllers/pullrequests.py:397 msgid "Successfully deleted pull request" msgstr "Prośba o skasowanie połączenia gałęzi została wykonana prawidłowo" -#: rhodecode/controllers/pullrequests.py:481 +#: kallithea/controllers/pullrequests.py:485 msgid "Closing with" msgstr "Zamykanie" -#: rhodecode/controllers/pullrequests.py:518 -msgid "" -"Closing pull request on other statuses than rejected or approved forbidden" -msgstr "Zamknij wszystkie wnioski połączenia gałęzi innych stanów niż odrzucony, zatwierdzony lub zabroniony" - -#: rhodecode/controllers/search.py:132 +#: kallithea/controllers/pullrequests.py:522 +msgid "Closing pull request on other statuses than rejected or approved forbidden" +msgstr "" +"Zamknij wszystkie wnioski połączenia gałęzi innych stanów niż odrzucony, " +"zatwierdzony lub zabroniony" + +#: kallithea/controllers/search.py:135 msgid "Invalid search query. Try quoting it." msgstr "Nieprawidłowe zapytania. Spróbuj zacytować go." -#: rhodecode/controllers/search.py:137 +#: kallithea/controllers/search.py:140 msgid "There is no index to search in. Please run whoosh indexer" msgstr "Nie ma szukanego indeksu. Proszę uruchomić indeksowanie whoosh" -#: rhodecode/controllers/search.py:141 +#: kallithea/controllers/search.py:144 msgid "An error occurred during this search operation" msgstr "Wystąpił błąd podczas wyszukiwania tej operacji" -#: rhodecode/controllers/summary.py:182 +#: kallithea/controllers/summary.py:203 msgid "No data loaded yet" msgstr "Żadne dane nie zostały załadowane" -#: rhodecode/controllers/summary.py:188 -#: rhodecode/templates/summary/summary.html:149 +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 msgid "Statistics are disabled for this repository" msgstr "Statystyki są wyłączone dla tego repozytorium" -#: rhodecode/controllers/admin/defaults.py:96 +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "Ustawienia autentykacji poprawnie zaktualizowane" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "wystapił błąd podczas uaktualniania ustawień autentykacji" + +#: kallithea/controllers/admin/defaults.py:97 msgid "Default settings updated successfully" msgstr "Domyślne ustawienia zostały pomyślnie zaktualizowane" -#: rhodecode/controllers/admin/defaults.py:110 +#: kallithea/controllers/admin/defaults.py:111 msgid "Error occurred during update of defaults" msgstr "wystąpił błąd podczas aktualizacji wartości domyślnych" -#: rhodecode/controllers/admin/gists.py:56 +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 msgid "forever" msgstr "na zawsze" -#: rhodecode/controllers/admin/gists.py:57 +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 msgid "5 minutes" msgstr "5 minut" -#: rhodecode/controllers/admin/gists.py:58 +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 msgid "1 hour" msgstr "1 godzina" -#: rhodecode/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 msgid "1 day" msgstr "1 dzień" -#: rhodecode/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 msgid "1 month" msgstr "1 miesiąc" -#: rhodecode/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 msgid "Lifetime" msgstr "Czas życia" -#: rhodecode/controllers/admin/gists.py:127 +#: kallithea/controllers/admin/gists.py:147 msgid "Error occurred during gist creation" msgstr "Wystąpił błąd podczas tworzenia git" -#: rhodecode/controllers/admin/gists.py:165 +#: kallithea/controllers/admin/gists.py:185 #, python-format msgid "Deleted gist %s" -msgstr "Usuń git %s" - -#: rhodecode/controllers/admin/ldap_settings.py:50 -msgid "BASE" -msgstr "PODSTAWA" - -#: rhodecode/controllers/admin/ldap_settings.py:51 -msgid "ONELEVEL" -msgstr "JEDEN POZIOM" - -#: rhodecode/controllers/admin/ldap_settings.py:52 -msgid "SUBTREE" -msgstr "DRZEWO PODRZĘDNE" - -#: rhodecode/controllers/admin/ldap_settings.py:56 -msgid "NEVER" -msgstr "NIGDY" - -#: rhodecode/controllers/admin/ldap_settings.py:57 -msgid "ALLOW" -msgstr "POZWÓL" - -#: rhodecode/controllers/admin/ldap_settings.py:58 -msgid "TRY" -msgstr "WYPRÓBUJ" - -#: rhodecode/controllers/admin/ldap_settings.py:59 -msgid "DEMAND" -msgstr "ZAPYTANIE" - -#: rhodecode/controllers/admin/ldap_settings.py:60 -msgid "HARD" -msgstr "TWARDY" - -#: rhodecode/controllers/admin/ldap_settings.py:64 -msgid "No encryption" -msgstr "Bez szyfrowania" - -#: rhodecode/controllers/admin/ldap_settings.py:65 -msgid "LDAPS connection" -msgstr "Połączenie LDAP" - -#: rhodecode/controllers/admin/ldap_settings.py:66 -msgid "START_TLS on LDAP connection" -msgstr "START_TLS dla połączenia LDAP" - -#: rhodecode/controllers/admin/ldap_settings.py:124 -msgid "LDAP settings updated successfully" -msgstr "Ustawienia LDAP zostały zaktualizowane" - -#: rhodecode/controllers/admin/ldap_settings.py:128 -msgid "Unable to activate ldap. The \"python-ldap\" library is missing." -msgstr "Nie można uaktywnić ldap.\"Python-ldap\" brakuje library." - -#: rhodecode/controllers/admin/ldap_settings.py:145 -msgid "Error occurred during update of ldap settings" -msgstr "Wystąpił błąd podczas aktualizacji ustawień ldap" - -#: rhodecode/controllers/admin/permissions.py:58 -#: rhodecode/controllers/admin/permissions.py:62 -#: rhodecode/controllers/admin/permissions.py:66 +msgstr "Usuń gist %s" + +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "" +"Nie możesz edytować tego użytkownika ponieważ jest kluczowy dla całej " +"aplikacji" + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "Twoje konto zostało pomyślnie zaktualizowane" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "wystąpił błąd podczas aktualizacji użytkownika %s" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "Dodano e-mail %s do użytkownika" + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "Wystąpił błąd podczas zapisywania e-maila" + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "Usunięto e-mail użytkownikowi" + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 msgid "None" msgstr "Brak" -#: rhodecode/controllers/admin/permissions.py:59 -#: rhodecode/controllers/admin/permissions.py:63 -#: rhodecode/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 msgid "Read" msgstr "Odczyt" -#: rhodecode/controllers/admin/permissions.py:60 -#: rhodecode/controllers/admin/permissions.py:64 -#: rhodecode/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 msgid "Write" msgstr "Zapis" -#: rhodecode/controllers/admin/permissions.py:61 -#: rhodecode/controllers/admin/permissions.py:65 -#: rhodecode/controllers/admin/permissions.py:69 -#: rhodecode/templates/admin/defaults/defaults.html:9 -#: rhodecode/templates/admin/ldap/ldap.html:9 -#: rhodecode/templates/admin/permissions/permissions.html:9 -#: rhodecode/templates/admin/repos/repo_add.html:10 -#: rhodecode/templates/admin/repos/repo_add.html:14 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:13 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:9 -#: rhodecode/templates/admin/users/user_add.html:8 -#: rhodecode/templates/admin/users/user_edit.html:9 -#: rhodecode/templates/admin/users/user_edit.html:133 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/admin/users/users.html:85 -#: rhodecode/templates/admin/users_groups/users_group_add.html:8 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 -#: rhodecode/templates/admin/users_groups/users_groups.html:9 -#: rhodecode/templates/base/base.html:317 -#: rhodecode/templates/base/base.html:318 -#: rhodecode/templates/base/base.html:324 -#: rhodecode/templates/base/base.html:325 +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 msgid "Admin" msgstr "Administracja" -#: rhodecode/controllers/admin/permissions.py:72 -#: rhodecode/controllers/admin/permissions.py:83 -#: rhodecode/controllers/admin/permissions.py:86 -#: rhodecode/controllers/admin/permissions.py:89 -#: rhodecode/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 msgid "Disabled" msgstr "Wyłączone" -#: rhodecode/controllers/admin/permissions.py:74 +#: kallithea/controllers/admin/permissions.py:78 msgid "Allowed with manual account activation" msgstr "Dozwolona z ręczną aktywacją konta" -#: rhodecode/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:80 msgid "Allowed with automatic account activation" msgstr "Dozwolona z automatyczną aktywacją konta" -#: rhodecode/controllers/admin/permissions.py:79 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1439 rhodecode/model/db.py:1444 +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 msgid "Manual activation of external account" msgstr "Ręczna aktywacja nowego konta" -#: rhodecode/controllers/admin/permissions.py:80 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1440 rhodecode/model/db.py:1445 +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 msgid "Automatic activation of external account" msgstr "Automatyczna aktywacja nowego konta" -#: rhodecode/controllers/admin/permissions.py:84 -#: rhodecode/controllers/admin/permissions.py:87 -#: rhodecode/controllers/admin/permissions.py:90 -#: rhodecode/controllers/admin/permissions.py:93 +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 msgid "Enabled" msgstr "Włączone" -#: rhodecode/controllers/admin/permissions.py:138 -msgid "Default permissions updated successfully" -msgstr "Domyślne uprawnienia zaktualizowane pomyślnie" - -#: rhodecode/controllers/admin/permissions.py:152 +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "Globalne uprawnienia zaktualizowane poprawnie" + +#: kallithea/controllers/admin/permissions.py:139 msgid "Error occurred during update of permissions" msgstr "Wystąpił błąd podczas aktualizacji uprawnień" -#: rhodecode/controllers/admin/repos.py:128 -msgid "--REMOVE FORK--" -msgstr "--USUŃ ROZGAŁĘZIENIE--" - -#: rhodecode/controllers/admin/repos.py:168 +#: kallithea/controllers/admin/repo_groups.py:186 +#, python-format +msgid "Created repository group %s" +msgstr "Utworzono grupę repo %s" + +#: kallithea/controllers/admin/repo_groups.py:198 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "Wystąpił błąd podczas tworzenia grupy repo %s" + +#: kallithea/controllers/admin/repo_groups.py:256 +#, python-format +msgid "Updated repository group %s" +msgstr "Zaktualizowano grupę repo %s" + +#: kallithea/controllers/admin/repo_groups.py:271 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "Wystąpił błąd podczas aktualizacji grupy repo %s" + +#: kallithea/controllers/admin/repo_groups.py:289 +#, python-format +msgid "This group contains %s repositores and cannot be deleted" +msgstr "Ta grupa zawiera %s repozytorium i nie może być usunięta" + +#: kallithea/controllers/admin/repo_groups.py:296 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "Ta grupa zawiera %s repozytorium i nie może być usunięta" + +#: kallithea/controllers/admin/repo_groups.py:302 +#, python-format +msgid "Removed repository group %s" +msgstr "Usunięto grupę repo %s" + +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "Wystąpił błąd podczas usuwania z repozytorium grupy %s" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "Nie można cofnąć zezwolenia dla admina jako admin" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "Aktualizacja uprawnień grup repozytorium" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "Wystąpił błąd podczas cofania zezwolenia" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "utworzone repozytorium %s" + +#: kallithea/controllers/admin/repos.py:237 #, python-format msgid "Created repository %s from %s" msgstr "utworzone repozytorium %s z %s" -#: rhodecode/controllers/admin/repos.py:174 +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "Gałęzi %s w repozytorium %s" + +#: kallithea/controllers/admin/repos.py:249 #, python-format msgid "Created repository %s" msgstr "Utworzone repozytorium %s" -#: rhodecode/controllers/admin/repos.py:197 -#, python-format -msgid "Error creating repository %s" -msgstr "utworzone repozytorium %s" - -#: rhodecode/controllers/admin/repos.py:270 +#: kallithea/controllers/admin/repos.py:289 #, python-format msgid "Repository %s updated successfully" msgstr "Repozytorium %s zostało pomyślnie zaktualizowane" -#: rhodecode/controllers/admin/repos.py:288 +#: kallithea/controllers/admin/repos.py:307 #, python-format msgid "Error occurred during update of repository %s" msgstr "Wystąpił błąd podczas aktualizacji repozytorium %s" -#: rhodecode/controllers/admin/repos.py:315 +#: kallithea/controllers/admin/repos.py:334 #, python-format msgid "Detached %s forks" msgstr "Oderwane rozgałęzienie %s" -#: rhodecode/controllers/admin/repos.py:318 +#: kallithea/controllers/admin/repos.py:337 #, python-format msgid "Deleted %s forks" msgstr "Usunięte repozytorium %s" -#: rhodecode/controllers/admin/repos.py:323 +#: kallithea/controllers/admin/repos.py:342 #, python-format msgid "Deleted repository %s" msgstr "Usunięte repozytorium %s" -#: rhodecode/controllers/admin/repos.py:326 +#: kallithea/controllers/admin/repos.py:345 #, python-format msgid "Cannot delete %s it still contains attached forks" msgstr "Nie można usunąć %s nadal zawiera załączniki rozgałęzienia" -#: rhodecode/controllers/admin/repos.py:331 +#: kallithea/controllers/admin/repos.py:350 #, python-format msgid "An error occurred during deletion of %s" msgstr "Wystąpił błąd podczas usuwania %s" -#: rhodecode/controllers/admin/repos.py:345 +#: kallithea/controllers/admin/repos.py:402 msgid "Repository permissions updated" -msgstr "Repozytorium wyłączone" - -#: rhodecode/controllers/admin/repos.py:375 -#: rhodecode/controllers/admin/repos_groups.py:332 -#: rhodecode/controllers/admin/users_groups.py:312 -msgid "An error occurred during revoking of permission" -msgstr "Wystąpił błąd podczas cofania zezwolenia" - -#: rhodecode/controllers/admin/repos.py:392 -msgid "An error occurred during deletion of repository stats" -msgstr "Wystąpił błąd podczas usuwania z repozytorium statystyk" - -#: rhodecode/controllers/admin/repos.py:409 -msgid "An error occurred during cache invalidation" -msgstr "Wystąpił błąd podczas unieważniania cache" - -#: rhodecode/controllers/admin/repos.py:429 -#: rhodecode/controllers/admin/repos.py:456 -msgid "An error occurred during unlocking" -msgstr "Wystąpił błąd podczas odblokowywania" - -#: rhodecode/controllers/admin/repos.py:447 -msgid "Unlocked" -msgstr "Odblokowany" - -#: rhodecode/controllers/admin/repos.py:450 -msgid "Locked" -msgstr "Zablokowany" - -#: rhodecode/controllers/admin/repos.py:452 -#, python-format -msgid "Repository has been %s" -msgstr "Repozytoriów jest %s" - -#: rhodecode/controllers/admin/repos.py:476 +msgstr "Uprawnienia repozytorium zostały zaktualizowane" + +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "Wystąpił błąd podczas tworzenia użytkownika %s" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "Wystąpił błąd podczas zapisywania e-maila" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "-- Brak rozgalezienia --" + +#: kallithea/controllers/admin/repos.py:522 msgid "Updated repository visibility in public journal" msgstr "Zaktualizowano widoczność stron w publicznym dzienniku" -#: rhodecode/controllers/admin/repos.py:480 +#: kallithea/controllers/admin/repos.py:526 msgid "An error occurred during setting this repository in public journal" msgstr "Wystąpił błąd podczas ustawiania tego repozytorium w dzienniku publicznym" -#: rhodecode/controllers/admin/repos.py:485 rhodecode/model/validators.py:302 +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 msgid "Token mismatch" msgstr "Niezgodność tokenu" -#: rhodecode/controllers/admin/repos.py:498 -msgid "Pulled from remote location" -msgstr "Pobieranie z lokalizacji zdalnej" - -#: rhodecode/controllers/admin/repos.py:501 -msgid "An error occurred during pull from remote location" -msgstr "Wystąpił błąd podczas pobierania z lokalizacji zdalnej" - -#: rhodecode/controllers/admin/repos.py:517 +#: kallithea/controllers/admin/repos.py:546 msgid "Nothing" msgstr "Brak" -#: rhodecode/controllers/admin/repos.py:519 +#: kallithea/controllers/admin/repos.py:548 #, python-format msgid "Marked repo %s as fork of %s" msgstr "Oznaczono %s repo jako rozwidlenie %s" -#: rhodecode/controllers/admin/repos.py:523 +#: kallithea/controllers/admin/repos.py:555 msgid "An error occurred during this operation" msgstr "Wystąpił błąd podczas tej operacji" -#: rhodecode/controllers/admin/repos.py:562 -msgid "An error occurred during creation of field" -msgstr "Wystąpił błąd podczas tworzenia użytkownika %s" - -#: rhodecode/controllers/admin/repos.py:576 -msgid "An error occurred during removal of field" -msgstr "Wystąpił błąd podczas zapisywania e-maila" - -#: rhodecode/controllers/admin/repos_groups.py:147 -#, python-format -msgid "Created repository group %s" -msgstr "Utworzono grupę repo %s" - -#: rhodecode/controllers/admin/repos_groups.py:159 -#, python-format -msgid "Error occurred during creation of repository group %s" -msgstr "Wystąpił błąd podczas tworzenia grupy repo %s" - -#: rhodecode/controllers/admin/repos_groups.py:217 -#, python-format -msgid "Updated repository group %s" -msgstr "Zaktualizowano grupę repo %s" - -#: rhodecode/controllers/admin/repos_groups.py:232 -#, python-format -msgid "Error occurred during update of repository group %s" -msgstr "Wystąpił błąd podczas aktualizacji grupy repo %s" - -#: rhodecode/controllers/admin/repos_groups.py:250 -#, python-format -msgid "This group contains %s repositores and cannot be deleted" -msgstr "Ta grupa zawiera %s repozytorium i nie może być usunięta" - -#: rhodecode/controllers/admin/repos_groups.py:257 -#, python-format -msgid "This group contains %s subgroups and cannot be deleted" -msgstr "Ta grupa zawiera %s repozytorium i nie może być usunięta" - -#: rhodecode/controllers/admin/repos_groups.py:263 -#, python-format -msgid "Removed repository group %s" -msgstr "Usunięto grupę repo %s" - -#: rhodecode/controllers/admin/repos_groups.py:268 -#, python-format -msgid "Error occurred during deletion of repository group %s" -msgstr "Wystąpił błąd podczas usuwania z repozytorium grupy %s" - -#: rhodecode/controllers/admin/repos_groups.py:279 -#: rhodecode/controllers/admin/repos_groups.py:314 -#: rhodecode/controllers/admin/users_groups.py:300 -msgid "Cannot revoke permission for yourself as admin" -msgstr "Nie można cofnąć zezwolenia dla admina jako admin" - -#: rhodecode/controllers/admin/repos_groups.py:294 -msgid "Repository Group permissions updated" -msgstr "Aktualizacja uprawnień grup repozytorium" - -#: rhodecode/controllers/admin/settings.py:123 +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "Zablokowane repozytorium" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "Odblokowane repozytorium" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 +msgid "An error occurred during unlocking" +msgstr "Wystąpił błąd podczas odblokowywania" + +#: kallithea/controllers/admin/repos.py:595 +msgid "Unlocked" +msgstr "Odblokowany" + +#: kallithea/controllers/admin/repos.py:598 +msgid "Locked" +msgstr "Zablokowany" + +#: kallithea/controllers/admin/repos.py:600 +#, python-format +msgid "Repository has been %s" +msgstr "Repozytoriów jest %s" + +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "Cache wyczyszczony poprawnie" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "Wystąpił błąd podczas unieważniania cache" + +#: kallithea/controllers/admin/repos.py:637 +msgid "Pulled from remote location" +msgstr "Pobieranie z lokalizacji zdalnej" + +#: kallithea/controllers/admin/repos.py:640 +msgid "An error occurred during pull from remote location" +msgstr "Wystąpił błąd podczas pobierania z lokalizacji zdalnej" + +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "Wystąpił błąd podczas usuwania z repozytorium statystyk" + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "Aktualizacja ustawień VCS" + +#: kallithea/controllers/admin/settings.py:176 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "Wystąpił błąd podczas aktualizacji ustawień aplikacji" + +#: kallithea/controllers/admin/settings.py:215 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" -msgstr "Repozytoria z powodzeniem zostały ponownie zeskanowane dodano: %s, usunięto: %s" - -#: rhodecode/controllers/admin/settings.py:132 -msgid "Whoosh reindex task scheduled" -msgstr "Zadanie ponownej indeksacji whoosh zostało zaplanowane" - -#: rhodecode/controllers/admin/settings.py:163 +msgstr "" +"Repozytoria z powodzeniem zostały ponownie zeskanowane dodano: %s, " +"usunięto: %s" + +#: kallithea/controllers/admin/settings.py:270 msgid "Updated application settings" msgstr "Aktualizacja ustawień aplikacji" -#: rhodecode/controllers/admin/settings.py:167 -#: rhodecode/controllers/admin/settings.py:304 -msgid "Error occurred during updating application settings" -msgstr "Wystąpił błąd podczas aktualizacji ustawień aplikacji" - -#: rhodecode/controllers/admin/settings.py:219 +#: kallithea/controllers/admin/settings.py:327 msgid "Updated visualisation settings" msgstr "Aktualizacja ustawień wizualizacji" -#: rhodecode/controllers/admin/settings.py:224 +#: kallithea/controllers/admin/settings.py:332 msgid "Error occurred during updating visualisation settings" msgstr "Wystąpił błąd podczas aktualizacji ustawień wizualizacji" -#: rhodecode/controllers/admin/settings.py:300 -msgid "Updated VCS settings" -msgstr "Aktualizacja ustawień VCS" - -#: rhodecode/controllers/admin/settings.py:314 +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "Proszę podać adres email" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "" + +#: kallithea/controllers/admin/settings.py:400 msgid "Added new hook" msgstr "Dodano nowy hook" -#: rhodecode/controllers/admin/settings.py:326 +#: kallithea/controllers/admin/settings.py:414 msgid "Updated hooks" msgstr "Aktualizacja hooku" -#: rhodecode/controllers/admin/settings.py:330 +#: kallithea/controllers/admin/settings.py:418 msgid "Error occurred during hook creation" msgstr "Wystąpił błąd podczas tworzenia hooku" -#: rhodecode/controllers/admin/settings.py:349 -msgid "Email task created" -msgstr "E-mail został wysłany" - -#: rhodecode/controllers/admin/settings.py:413 -msgid "You can't edit this user since it's crucial for entire application" -msgstr "Nie możesz edytować tego użytkownika ponieważ jest kluczowy dla całej aplikacji" - -#: rhodecode/controllers/admin/settings.py:455 -msgid "Your account was updated successfully" -msgstr "Twoje konto zostało pomyślnie zaktualizowane" - -#: rhodecode/controllers/admin/settings.py:470 -#: rhodecode/controllers/admin/users.py:198 -#, python-format -msgid "Error occurred during update of user %s" -msgstr "wystąpił błąd podczas aktualizacji użytkownika %s" - -#: rhodecode/controllers/admin/users.py:130 +#: kallithea/controllers/admin/settings.py:444 +msgid "Whoosh reindex task scheduled" +msgstr "Zadanie ponownej indeksacji whoosh zostało zaplanowane" + +#: kallithea/controllers/admin/user_groups.py:150 +#, python-format +msgid "Created user group %s" +msgstr "Utworzono grupę użytkowników %s" + +#: kallithea/controllers/admin/user_groups.py:161 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "Wystąpił błąd podczas tworzenia grupy użytkowników %s" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Updated user group %s" +msgstr "Zaktualizowano grupę użytkowników %s" + +#: kallithea/controllers/admin/user_groups.py:221 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "Wystąpił błąd podczas aktualizacji grupy użytkowników %s" + +#: kallithea/controllers/admin/user_groups.py:239 +msgid "Successfully deleted user group" +msgstr "Grupa użytkowników została usunięta z powodzeniem" + +#: kallithea/controllers/admin/user_groups.py:244 +msgid "An error occurred during deletion of user group" +msgstr "Wystąpił błąd podczas usuwania grupy użytkowników" + +#: kallithea/controllers/admin/user_groups.py:311 +msgid "Target group cannot be the same" +msgstr "Grupa docelowa nie może być taka sama" + +#: kallithea/controllers/admin/user_groups.py:317 +msgid "User Group permissions updated" +msgstr "Aktualizacja uprawnień grupy użytkowników" + +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "Aktualizacja uprawnień" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "Wystąpił błąd podczas zapisywania uprawnień" + +#: kallithea/controllers/admin/users.py:135 #, python-format msgid "Created user %s" msgstr "Utworzono użytkownika %s" -#: rhodecode/controllers/admin/users.py:142 +#: kallithea/controllers/admin/users.py:149 #, python-format msgid "Error occurred during creation of user %s" msgstr "Wystąpił błąd podczas tworzenia użytkownika %s" -#: rhodecode/controllers/admin/users.py:176 +#: kallithea/controllers/admin/users.py:188 msgid "User updated successfully" msgstr "Użytkownik został zaktualizowany" -#: rhodecode/controllers/admin/users.py:214 +#: kallithea/controllers/admin/users.py:223 msgid "Successfully deleted user" msgstr "Użytkownik został usunięty" -#: rhodecode/controllers/admin/users.py:219 +#: kallithea/controllers/admin/users.py:228 msgid "An error occurred during deletion of user" msgstr "Wystąpił błąd podczas usuwania użytkownika" -#: rhodecode/controllers/admin/users.py:234 +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 msgid "You can't edit this user" msgstr "Nie możesz edytować tego użytkownika" -#: rhodecode/controllers/admin/users.py:293 -#: rhodecode/controllers/admin/users_groups.py:372 -msgid "Updated permissions" -msgstr "Aktualizacja uprawnień" - -#: rhodecode/controllers/admin/users.py:297 -#: rhodecode/controllers/admin/users_groups.py:376 -msgid "An error occurred during permissions saving" -msgstr "Wystąpił błąd podczas zapisywania uprawnień" - -#: rhodecode/controllers/admin/users.py:311 -#, python-format -msgid "Added email %s to user" -msgstr "Dodano e-mail %s do użytkownika" - -#: rhodecode/controllers/admin/users.py:317 -msgid "An error occurred during email saving" -msgstr "Wystąpił błąd podczas zapisywania e-maila" - -#: rhodecode/controllers/admin/users.py:327 -msgid "Removed email from user" -msgstr "Usunięto e-mail użytkownikowi" - -#: rhodecode/controllers/admin/users.py:340 -#, python-format -msgid "Added ip %s to user" -msgstr "Dodano e-mail %s do użytkownika" - -#: rhodecode/controllers/admin/users.py:346 +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "Dodano ip %s do listy dozwolonych adresów użytkownia" + +#: kallithea/controllers/admin/users.py:489 msgid "An error occurred during ip saving" msgstr "Wystąpił błąd podczas zapisywania e-maila" -#: rhodecode/controllers/admin/users.py:358 -msgid "Removed ip from user" -msgstr "Usunięto e-mail użytkownikowi" - -#: rhodecode/controllers/admin/users_groups.py:162 -#, python-format -msgid "Created user group %s" -msgstr "Utworzono grupę użytkowników %s" - -#: rhodecode/controllers/admin/users_groups.py:173 -#, python-format -msgid "Error occurred during creation of user group %s" -msgstr "Wystąpił błąd podczas tworzenia grupy użytkowników %s" - -#: rhodecode/controllers/admin/users_groups.py:210 -#, python-format -msgid "Updated user group %s" -msgstr "Zaktualizowano grupę użytkowników %s" - -#: rhodecode/controllers/admin/users_groups.py:232 -#, python-format -msgid "Error occurred during update of user group %s" -msgstr "Wystąpił błąd podczas aktualizacji grupy użytkowników %s" - -#: rhodecode/controllers/admin/users_groups.py:250 -msgid "Successfully deleted user group" -msgstr "Grupa użytkowników została usunięta z powodzeniem" - -#: rhodecode/controllers/admin/users_groups.py:255 -msgid "An error occurred during deletion of user group" -msgstr "Wystąpił błąd podczas usuwania grupy użytkowników" - -#: rhodecode/controllers/admin/users_groups.py:274 -msgid "Target group cannot be the same" -msgstr "Grupa docelowa nie może być taka sama" - -#: rhodecode/controllers/admin/users_groups.py:280 -msgid "User Group permissions updated" -msgstr "Aktualizacja uprawnień grupy użytkowników" - -#: rhodecode/lib/auth.py:544 +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "Usunięto adres ip z listy dozwolonych adresów dla użytkownika" + +#: kallithea/lib/auth.py:748 #, python-format msgid "IP %s not allowed" msgstr "Obserwatorzy %s" -#: rhodecode/lib/auth.py:593 +#: kallithea/lib/auth.py:809 msgid "You need to be a registered user to perform this action" msgstr "Musisz być zarejestrowanym użytkownikiem, żeby wykonać to działanie" -#: rhodecode/lib/auth.py:634 +#: kallithea/lib/auth.py:846 msgid "You need to be a signed in to view this page" msgstr "Musisz być zalogowany, żeby oglądać stronę" -#: rhodecode/lib/diffs.py:66 +#: kallithea/lib/diffs.py:66 msgid "Binary file" msgstr "Plik binarny" -#: rhodecode/lib/diffs.py:82 -msgid "" -"Changeset was too big and was cut off, use diff menu to display this diff" -msgstr "Lista zmian była zbyt duża i została obcięta, użyj menu porównań żeby wyświetlić różnice" - -#: rhodecode/lib/diffs.py:92 +#: kallithea/lib/diffs.py:82 +msgid "Changeset was too big and was cut off, use diff menu to display this diff" +msgstr "" +"Lista zmian była zbyt duża i została obcięta, użyj menu porównań żeby " +"wyświetlić różnice" + +#: kallithea/lib/diffs.py:92 msgid "No changes detected" msgstr "Nie wykryto zmian" -#: rhodecode/lib/helpers.py:539 -msgid "True" -msgstr "Prawda" - -#: rhodecode/lib/helpers.py:542 -msgid "False" -msgstr "Fałsz" - -#: rhodecode/lib/helpers.py:580 +#: kallithea/lib/helpers.py:598 #, python-format msgid "Deleted branch: %s" msgstr "Usunięta gałąź: %s" -#: rhodecode/lib/helpers.py:583 +#: kallithea/lib/helpers.py:601 #, python-format msgid "Created tag: %s" msgstr "Utworzony tag: %s" -#: rhodecode/lib/helpers.py:596 +#: kallithea/lib/helpers.py:614 msgid "Changeset not found" msgstr "Nie znaleziono changeset" -#: rhodecode/lib/helpers.py:646 +#: kallithea/lib/helpers.py:664 #, python-format msgid "Show all combined changesets %s->%s" msgstr "Pokaż wszystkie zestawienia zmian changesets %s->%s" -#: rhodecode/lib/helpers.py:652 +#: kallithea/lib/helpers.py:670 msgid "compare view" msgstr "Wyświetl porównanie" -#: rhodecode/lib/helpers.py:672 +#: kallithea/lib/helpers.py:690 msgid "and" msgstr "i" -#: rhodecode/lib/helpers.py:673 +#: kallithea/lib/helpers.py:691 #, python-format msgid "%s more" msgstr "%s więcej" -#: rhodecode/lib/helpers.py:674 -#: rhodecode/templates/changelog/changelog.html:53 +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 msgid "revisions" msgstr "rewizja" -#: rhodecode/lib/helpers.py:698 +#: kallithea/lib/helpers.py:716 #, python-format msgid "fork name %s" msgstr "nazwa rozgałęzienia %s" -#: rhodecode/lib/helpers.py:715 -#: rhodecode/templates/pullrequests/pullrequest_show.html:8 +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 #, python-format msgid "Pull request #%s" msgstr "Połączonych gałęzi #%s" -#: rhodecode/lib/helpers.py:725 +#: kallithea/lib/helpers.py:743 msgid "[deleted] repository" msgstr "[usunięte] repozytorium" -#: rhodecode/lib/helpers.py:727 rhodecode/lib/helpers.py:739 +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 msgid "[created] repository" msgstr "[utworzone] repozytorium" -#: rhodecode/lib/helpers.py:729 +#: kallithea/lib/helpers.py:747 msgid "[created] repository as fork" msgstr "[utworzone] repozytorium jako rozgałęzienie" -#: rhodecode/lib/helpers.py:731 rhodecode/lib/helpers.py:741 +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 msgid "[forked] repository" msgstr "[rozgałęzione] repozytorium" -#: rhodecode/lib/helpers.py:733 rhodecode/lib/helpers.py:743 +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 msgid "[updated] repository" msgstr "[zaktualizowane] repozytorium" -#: rhodecode/lib/helpers.py:735 +#: kallithea/lib/helpers.py:753 msgid "[downloaded] archive from repository" msgstr "[pobierz] archiwum z repozytorium" -#: rhodecode/lib/helpers.py:737 +#: kallithea/lib/helpers.py:755 msgid "[delete] repository" msgstr "[skasowane] repozytorium" -#: rhodecode/lib/helpers.py:745 +#: kallithea/lib/helpers.py:763 msgid "[created] user" msgstr "[utworzony] użytkownik" -#: rhodecode/lib/helpers.py:747 +#: kallithea/lib/helpers.py:765 msgid "[updated] user" msgstr "[zaktualizowany] użytkownik" -#: rhodecode/lib/helpers.py:749 +#: kallithea/lib/helpers.py:767 msgid "[created] user group" msgstr "[utworzona] grupa użytkowników" -#: rhodecode/lib/helpers.py:751 +#: kallithea/lib/helpers.py:769 msgid "[updated] user group" msgstr "[zaktualizowana] grupa użytkowników" -#: rhodecode/lib/helpers.py:753 +#: kallithea/lib/helpers.py:771 msgid "[commented] on revision in repository" msgstr "[komentarz] do zmiany w repozytorium" -#: rhodecode/lib/helpers.py:755 +#: kallithea/lib/helpers.py:773 msgid "[commented] on pull request for" msgstr "[komentarz] wniosek o połączenie gałęzi" -#: rhodecode/lib/helpers.py:757 +#: kallithea/lib/helpers.py:775 msgid "[closed] pull request for" msgstr "[zamknięty] wniosek o połączenie gałęzi" -#: rhodecode/lib/helpers.py:759 +#: kallithea/lib/helpers.py:777 msgid "[pushed] into" msgstr "[wysłane zmiany] w" -#: rhodecode/lib/helpers.py:761 -msgid "[committed via RhodeCode] into repository" -msgstr "[synchronizacja przez RhodeCode] z repozytorium" - -#: rhodecode/lib/helpers.py:763 +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "[synchronizacja przez Kallithea] z repozytorium" + +#: kallithea/lib/helpers.py:781 msgid "[pulled from remote] into repository" msgstr "[pobieranie z zdalnego] do repozytorium" -#: rhodecode/lib/helpers.py:765 +#: kallithea/lib/helpers.py:783 msgid "[pulled] from" msgstr "[pobrano] " -#: rhodecode/lib/helpers.py:767 +#: kallithea/lib/helpers.py:785 msgid "[started following] repository" msgstr "[start następnego] repozytorium" -#: rhodecode/lib/helpers.py:769 +#: kallithea/lib/helpers.py:787 msgid "[stopped following] repository" msgstr "[zatrzymany po] repozytorium" -#: rhodecode/lib/helpers.py:1088 +#: kallithea/lib/helpers.py:1101 #, python-format msgid " and %s more" msgstr "i %s więcej" -#: rhodecode/lib/helpers.py:1092 +#: kallithea/lib/helpers.py:1105 msgid "No Files" msgstr "Brak Plików" -#: rhodecode/lib/helpers.py:1158 +#: kallithea/lib/helpers.py:1171 msgid "new file" msgstr "nowy plik" -#: rhodecode/lib/helpers.py:1161 +#: kallithea/lib/helpers.py:1174 msgid "mod" msgstr "modyfikuj" -#: rhodecode/lib/helpers.py:1164 +#: kallithea/lib/helpers.py:1177 msgid "del" msgstr "kasuj" -#: rhodecode/lib/helpers.py:1167 +#: kallithea/lib/helpers.py:1180 msgid "rename" msgstr "zmień nazwę" -#: rhodecode/lib/helpers.py:1172 +#: kallithea/lib/helpers.py:1185 msgid "chmod" msgstr "chmod" -#: rhodecode/lib/helpers.py:1404 +#: kallithea/lib/helpers.py:1417 #, python-format msgid "" -"%s repository is not mapped to db perhaps it was created or renamed from the" -" filesystem please run the application again in order to rescan repositories" -msgstr "%s repozytorium nie jest mapowane do db może zostało utworzone lub zmienione z systemie plików proszę uruchomić aplikację ponownie, aby ponownie przeskanować repozytoria" - -#: rhodecode/lib/unionrepo.py:193 -msgid "cannot create new union repository" -msgstr "[utworzone] repozytorium" - -#: rhodecode/lib/utils2.py:410 +"%s repository is not mapped to db perhaps it was created or renamed from " +"the filesystem please run the application again in order to rescan " +"repositories" +msgstr "" +"%s repozytorium nie jest mapowane do db może zostało utworzone lub " +"zmienione z systemie plików proszę uruchomić aplikację ponownie, aby " +"ponownie przeskanować repozytoria" + +#: kallithea/lib/utils2.py:415 #, python-format msgid "%d year" msgid_plural "%d years" @@ -1037,7 +1155,7 @@ msgstr[0] "%d rok" msgstr[1] "%d lata" msgstr[2] "%d lat" -#: rhodecode/lib/utils2.py:411 +#: kallithea/lib/utils2.py:416 #, python-format msgid "%d month" msgid_plural "%d months" @@ -1045,7 +1163,7 @@ msgstr[0] "%d miesiąc" msgstr[1] "%d miesięcy" msgstr[2] "%d miesięcy" -#: rhodecode/lib/utils2.py:412 +#: kallithea/lib/utils2.py:417 #, python-format msgid "%d day" msgid_plural "%d days" @@ -1053,7 +1171,7 @@ msgstr[0] "%d dzień" msgstr[1] "%d dni" msgstr[2] "%d dni" -#: rhodecode/lib/utils2.py:413 +#: kallithea/lib/utils2.py:418 #, python-format msgid "%d hour" msgid_plural "%d hours" @@ -1061,7 +1179,7 @@ msgstr[0] "%d godzina" msgstr[1] "%d godziny" msgstr[2] "%d godzin" -#: rhodecode/lib/utils2.py:414 +#: kallithea/lib/utils2.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" @@ -1069,7 +1187,7 @@ msgstr[0] "%d minuta" msgstr[1] "%d minuty" msgstr[2] "%d minut" -#: rhodecode/lib/utils2.py:415 +#: kallithea/lib/utils2.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" @@ -1077,833 +1195,1081 @@ msgstr[0] "%d sekunda" msgstr[1] "%d sekund" msgstr[2] "%d sekund" -#: rhodecode/lib/utils2.py:431 +#: kallithea/lib/utils2.py:436 #, python-format msgid "in %s" msgstr "w %s" -#: rhodecode/lib/utils2.py:433 +#: kallithea/lib/utils2.py:438 #, python-format msgid "%s ago" msgstr "%s temu" -#: rhodecode/lib/utils2.py:435 +#: kallithea/lib/utils2.py:440 #, python-format msgid "in %s and %s" msgstr "w %s i %s" -#: rhodecode/lib/utils2.py:438 +#: kallithea/lib/utils2.py:443 #, python-format msgid "%s and %s ago" msgstr "%s i %s temu" -#: rhodecode/lib/utils2.py:441 +#: kallithea/lib/utils2.py:446 msgid "just now" msgstr "przed chwilą" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1163 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1303 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1388 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1408 rhodecode/model/db.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 msgid "Repository no access" msgstr "Brak dostępu do repozytorium" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1164 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1184 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1304 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1389 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1409 rhodecode/model/db.py:1414 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 msgid "Repository read access" msgstr "Repozytorium do odczytu" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1165 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1185 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1305 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1390 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1410 rhodecode/model/db.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 msgid "Repository write access" msgstr "Repozytorium do zapisu" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1166 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1186 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1306 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1391 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1411 rhodecode/model/db.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 msgid "Repository admin access" msgstr "Administracja dostępu do repozytorium" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1168 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 msgid "Repositories Group no access" msgstr "Grupy repozytoriów brak dostępu" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1169 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1309 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 msgid "Repositories Group read access" msgstr "Grupy repozytoriów dostęp do odczytu" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1170 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1310 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 msgid "Repositories Group write access" msgstr "Grupy repozytoriów dostęp do zapisu" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1171 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1311 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 msgid "Repositories Group admin access" msgstr "Repozytoria Grupy dostęp administratora" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1173 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1193 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1313 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1398 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1406 rhodecode/model/db.py:1411 -msgid "RhodeCode Administrator" +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" msgstr "Administrator Repo" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1174 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1194 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1314 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1399 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1429 rhodecode/model/db.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 msgid "Repository creation disabled" -msgstr "Repozytorium wyłączone" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1175 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1195 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1315 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1400 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1430 rhodecode/model/db.py:1435 +msgstr "Tworzenie repozytorium jest wyłączone" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 msgid "Repository creation enabled" -msgstr "Repozytorium włączone" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1176 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1196 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1316 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1401 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1432 rhodecode/model/db.py:1437 +msgstr "Tworzenie repozytorium jest włączone" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 msgid "Repository forking disabled" msgstr "Rozwidlenie repozytorium wyłączone" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1177 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1197 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1317 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1402 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1433 rhodecode/model/db.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 msgid "Repository forking enabled" msgstr "Rozwidlenie repozytorium włączone" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1178 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1318 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 msgid "Register disabled" msgstr "Rejestracja wyłączona" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1319 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1404 -msgid "Register new user with RhodeCode with manual activation" +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" msgstr "Rejestracja nowego użytkownika na stronie z ręczną aktywacją" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1202 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1407 -msgid "Register new user with RhodeCode with auto activation" +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" msgstr "Rejestracja nowego użytkownika na stronie z automatyczną aktywacją" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1623 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1643 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1763 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1838 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1934 rhodecode/model/db.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 msgid "Not Reviewed" msgstr "Brak Korekty" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1624 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1644 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1764 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1839 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1935 rhodecode/model/db.py:1940 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 msgid "Approved" msgstr "Zaakceptowano" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1625 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1645 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1765 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1840 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1936 rhodecode/model/db.py:1941 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 msgid "Rejected" msgstr "Odrzucono" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1626 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1646 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1766 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1841 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1937 rhodecode/model/db.py:1942 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 msgid "Under Review" msgstr "Objęty Przeglądem" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1252 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1270 rhodecode/model/db.py:1275 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 msgid "top level" msgstr "najwyższy poziom" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1393 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1413 rhodecode/model/db.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 msgid "Repository group no access" msgstr "Grupy repozytoriów brak dostępu" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1394 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1414 rhodecode/model/db.py:1419 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 msgid "Repository group read access" msgstr "Grupy repozytoriów dostęp do odczytu" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1395 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1415 rhodecode/model/db.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 msgid "Repository group write access" msgstr "Grupy repozytoriów dostęp do zapisu" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1396 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1416 rhodecode/model/db.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 msgid "Repository group admin access" msgstr "Repozytoria Grupy dostęp administratora" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1418 rhodecode/model/db.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 msgid "User group no access" msgstr "Ta grupa użytkowników nie ma dostępu" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1419 rhodecode/model/db.py:1424 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 msgid "User group read access" msgstr "Dostęp do grupy parametrów użytkownika" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1420 rhodecode/model/db.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 msgid "User group write access" msgstr "Ta grupa użytkowników ma prawo do zapisu" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1421 rhodecode/model/db.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 msgid "User group admin access" msgstr "Ta grupa użytkowników ma uprawnienia administratora" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1423 rhodecode/model/db.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 msgid "Repository Group creation disabled" msgstr "Tworzenie grup repozytoriów wyłączone" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1424 rhodecode/model/db.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 msgid "Repository Group creation enabled" msgstr "Tworzenie grup repozytoriów włączone" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1426 rhodecode/model/db.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 msgid "User Group creation disabled" msgstr "Tworzenie grup użytkowników wyłączone" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1427 rhodecode/model/db.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 msgid "User Group creation enabled" msgstr "Tworzenie grup użytkowników właczone" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1435 rhodecode/model/db.py:1440 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 msgid "Registration disabled" msgstr "Rejestracja wyłączona" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1436 rhodecode/model/db.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 msgid "User Registration with manual account activation" msgstr "Rejestracja użytkownika z ręczną aktywacją konta" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1437 rhodecode/model/db.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 msgid "User Registration with automatic account activation" msgstr "Rejestracja użytkownika z automatyczną aktywacją konta" -#: rhodecode/model/comment.py:75 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:77 #, python-format msgid "on line %s" msgstr "widziany %s" -#: rhodecode/model/comment.py:220 +#: kallithea/model/comment.py:222 msgid "[Mention]" msgstr "[Wymieniony]" -#: rhodecode/model/forms.py:43 +#: kallithea/model/forms.py:57 msgid "Please enter a login" msgstr "Wpisz login" -#: rhodecode/model/forms.py:44 +#: kallithea/model/forms.py:58 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "Wprowadź wartość %(min)i znaków lub więcej" -#: rhodecode/model/forms.py:52 +#: kallithea/model/forms.py:66 msgid "Please enter a password" msgstr "Wpisz hasło" -#: rhodecode/model/forms.py:53 +#: kallithea/model/forms.py:67 #, python-format msgid "Enter %(min)i characters or more" msgstr "Wpisz %(min)i lub więcej znaków" -#: rhodecode/model/notification.py:228 +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:231 #, python-format msgid "%(user)s commented on changeset at %(when)s" msgstr "%(user)s skomentował zatwierdzenie %(when)s" -#: rhodecode/model/notification.py:229 +#: kallithea/model/notification.py:232 #, python-format msgid "%(user)s sent message at %(when)s" msgstr "%(user)s wysłał wiadomość do %(when)s" -#: rhodecode/model/notification.py:230 +#: kallithea/model/notification.py:233 #, python-format msgid "%(user)s mentioned you at %(when)s" msgstr "%(user)s wspomniał o Tobie w %(when)s" -#: rhodecode/model/notification.py:231 -#, python-format -msgid "%(user)s registered in RhodeCode at %(when)s" +#: kallithea/model/notification.py:234 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" msgstr "%(user)s zarejestrował na stronie w %(when)s" -#: rhodecode/model/notification.py:232 +#: kallithea/model/notification.py:235 #, python-format msgid "%(user)s opened new pull request at %(when)s" msgstr "%(user)s otworzył nowe połączenie gałęzi w %(when)s" -#: rhodecode/model/notification.py:233 +#: kallithea/model/notification.py:236 #, python-format msgid "%(user)s commented on pull request at %(when)s" msgstr "%(user)s skomentował nowe połączenie gałęzi w %(when)s" -#: rhodecode/model/pull_request.py:98 +#: kallithea/model/pull_request.py:107 #, python-format msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" msgstr "%(user)s chce żeby przejrzeć nowe gałęzie #%(pr_id)s: %(pr_title)s" -#: rhodecode/model/scm.py:674 +#: kallithea/model/scm.py:810 msgid "latest tip" msgstr "ostatni tip" -#: rhodecode/model/user.py:232 +#: kallithea/model/user.py:198 msgid "New user registration" msgstr "nowy użytkownik się zarejestrował" -#: rhodecode/model/user.py:257 rhodecode/model/user.py:281 +#: kallithea/model/user.py:222 kallithea/model/user.py:247 msgid "You can't Edit this user since it's crucial for entire application" -msgstr "Nie możesz edytować tego użytkownika ponieważ jest kluczowy dla całej aplikacji" - -#: rhodecode/model/user.py:303 +msgstr "" +"Nie możesz edytować tego użytkownika ponieważ jest kluczowy dla całej " +"aplikacji" + +#: kallithea/model/user.py:270 msgid "You can't remove this user since it's crucial for entire application" -msgstr "Nie możesz usunąć tego użytkownika ponieważ jest kluczowy dla całej aplikacji" - -#: rhodecode/model/user.py:309 +msgstr "" +"Nie możesz usunąć tego użytkownika ponieważ jest kluczowy dla całej " +"aplikacji" + +#: kallithea/model/user.py:276 #, python-format msgid "" -"user \"%s\" still owns %s repositories and cannot be removed. Switch owners " -"or remove those repositories. %s" -msgstr "użytkownik \"%s\" wciąż posiada repozytoria następujące %s i nie może zostać usunięty. Zmień właściciela lub usuń te repozytoria. %s" - -#: rhodecode/model/user.py:334 +"user \"%s\" still owns %s repositories and cannot be removed. Switch " +"owners or remove those repositories. %s" +msgstr "" +"użytkownik \"%s\" wciąż posiada repozytoria następujące %s i nie może " +"zostać usunięty. Zmień właściciela lub usuń te repozytoria. %s" + +#: kallithea/model/user.py:304 msgid "Password reset link" msgstr "łącze resetowania hasła" -#: rhodecode/model/user.py:366 +#: kallithea/model/user.py:333 msgid "Your new password" msgstr "Nowe hasło" -#: rhodecode/model/user.py:367 -#, python-format -msgid "Your new RhodeCode password:%s" +#: kallithea/model/user.py:334 +#, python-format +msgid "Your new Kallithea password:%s" msgstr "Nowe hasło do strony: %s" -#: rhodecode/model/validators.py:38 rhodecode/model/validators.py:39 +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 msgid "Value cannot be an empty list" msgstr "Wartość listy nie może być pusta" -#: rhodecode/model/validators.py:85 +#: kallithea/model/validators.py:120 #, python-format msgid "Username \"%(username)s\" already exists" msgstr "Użytkownik \"%(username)s\" już istnieje" -#: rhodecode/model/validators.py:87 +#: kallithea/model/validators.py:122 #, python-format msgid "Username \"%(username)s\" is forbidden" msgstr "Nazwa użytkownika \"%(username)s\" jest zabroniona" -#: rhodecode/model/validators.py:89 +#: kallithea/model/validators.py:124 msgid "" -"Username may only contain alphanumeric characters underscores, periods or " -"dashes and must begin with alphanumeric character or underscore" -msgstr "Nazwa użytkownika może zawierać tylko znaki alfanumeryczne, podkreślenia, kropki lub myślniki i muszą zaczynać się znakiem alfanumerycznym lub podkreśleniem" - -#: rhodecode/model/validators.py:117 +"Username may only contain alphanumeric characters underscores, periods or" +" dashes and must begin with alphanumeric character or underscore" +msgstr "" +"Nazwa użytkownika może zawierać tylko znaki alfanumeryczne, podkreślenia," +" kropki lub myślniki i muszą zaczynać się znakiem alfanumerycznym lub " +"podkreśleniem" + +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:158 #, python-format msgid "Username %(username)s is not valid" msgstr "Nazwa użytkownika %(username)s jest nieprawidłowa" -#: rhodecode/model/validators.py:136 +#: kallithea/model/validators.py:177 msgid "Invalid user group name" msgstr "Niewłaściwa nazwa grupy" -#: rhodecode/model/validators.py:137 +#: kallithea/model/validators.py:178 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "Nazwa grupy \"%(usergroup)s\" już istnieje" -#: rhodecode/model/validators.py:139 +#: kallithea/model/validators.py:180 msgid "" "user group name may only contain alphanumeric characters underscores, " "periods or dashes and must begin with alphanumeric character" -msgstr "nazwa grupy może zawierać tylko znaki alfanumeryczne, podkreślenia, kropki lub myślniki i musi zaczynać się znakiem alfanumerycznym" - -#: rhodecode/model/validators.py:177 +msgstr "" +"nazwa grupy może zawierać tylko znaki alfanumeryczne, podkreślenia, " +"kropki lub myślniki i musi zaczynać się znakiem alfanumerycznym" + +#: kallithea/model/validators.py:218 msgid "Cannot assign this group as parent" msgstr "Nie można przypisać do tej grupy jako rodzic" -#: rhodecode/model/validators.py:178 +#: kallithea/model/validators.py:219 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "Nazwa grupy \"%(group_name)s\" już istnieje" -#: rhodecode/model/validators.py:180 +#: kallithea/model/validators.py:221 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "Repozytorium o nazwie \"%(group_name)s\" już istnieje" -#: rhodecode/model/validators.py:238 +#: kallithea/model/validators.py:279 msgid "Invalid characters (non-ascii) in password" msgstr "Nieprawidłowe znaki (nie-ascii) w haśle" -#: rhodecode/model/validators.py:253 +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 msgid "Passwords do not match" msgstr "Hasła różnią się" -#: rhodecode/model/validators.py:270 +#: kallithea/model/validators.py:327 msgid "invalid password" msgstr "nieprawidłowe hasło" -#: rhodecode/model/validators.py:271 +#: kallithea/model/validators.py:328 msgid "invalid user name" msgstr "niepoprawna nazwa użytkownika" -#: rhodecode/model/validators.py:272 +#: kallithea/model/validators.py:329 msgid "Your account is disabled" msgstr "Twoje konto jest wyłączone" -#: rhodecode/model/validators.py:316 +#: kallithea/model/validators.py:373 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "Nazwa repozytorium %(repo)s jest zabroniona" -#: rhodecode/model/validators.py:318 +#: kallithea/model/validators.py:375 #, python-format msgid "Repository named %(repo)s already exists" msgstr "Repozytorium o nazwie %(repo)s już istnieje" -#: rhodecode/model/validators.py:319 +#: kallithea/model/validators.py:376 #, python-format msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" msgstr "Repozytorium \"%(repo)s\" już istnieje w grupie \"%(group)s\"" -#: rhodecode/model/validators.py:321 +#: kallithea/model/validators.py:378 #, python-format msgid "Repository group with name \"%(repo)s\" already exists" msgstr "Grupa repozytoriów z nazwą \"%(repo)s\" już istnieje" -#: rhodecode/model/validators.py:438 +#: kallithea/model/validators.py:493 msgid "invalid clone url" msgstr "nieprawidłowe url klonowania" -#: rhodecode/model/validators.py:439 +#: kallithea/model/validators.py:494 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" msgstr "Nieprawidłowe url klonowania, wstaw prawidłowy url http(s)/svn+http(s)" -#: rhodecode/model/validators.py:464 +#: kallithea/model/validators.py:519 msgid "Fork have to be the same type as parent" msgstr "Fork musi być tego samego typu, jak rodzic" -#: rhodecode/model/validators.py:479 +#: kallithea/model/validators.py:534 msgid "You don't have permissions to create repository in this group" msgstr "Nie masz uprawnień do tworzenia repozytorium w tej grupie" -#: rhodecode/model/validators.py:481 +#: kallithea/model/validators.py:536 msgid "no permission to create repository in root location" msgstr "nie masz uprawnień do tworzenia repozytorium w tej grupie" -#: rhodecode/model/validators.py:518 +#: kallithea/model/validators.py:585 msgid "You don't have permissions to create a group in this location" msgstr "Nie masz uprawnień do tworzenia repozytorium w tej grupie" -#: rhodecode/model/validators.py:559 +#: kallithea/model/validators.py:626 msgid "This username or user group name is not valid" msgstr "Ta nazwa użytkownika lub grupy użytkowników nie jest prawidłowa" -#: rhodecode/model/validators.py:652 +#: kallithea/model/validators.py:719 msgid "This is not a valid path" msgstr "To nie jest prawidłowa ścieżka" -#: rhodecode/model/validators.py:667 +#: kallithea/model/validators.py:734 msgid "This e-mail address is already taken" msgstr "Ten adres e-mail jest już zajęty" -#: rhodecode/model/validators.py:687 +#: kallithea/model/validators.py:754 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "e-mail \"%(email)s\" nie istnieje." -#: rhodecode/model/validators.py:724 +#: kallithea/model/validators.py:791 msgid "" -"The LDAP Login attribute of the CN must be specified - this is the name of " -"the attribute that is equivalent to \"username\"" -msgstr "Atrybut logowania CN do LDAP należy określić, jest to nazwa atrybutu, który jest odpowiednikiem \"username\"" - -#: rhodecode/model/validators.py:737 +"The LDAP Login attribute of the CN must be specified - this is the name " +"of the attribute that is equivalent to \"username\"" +msgstr "" +"Atrybut logowania CN do LDAP należy określić, jest to nazwa atrybutu, " +"który jest odpowiednikiem \"username\"" + +#: kallithea/model/validators.py:804 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" msgstr "Rewizja %(revs)s jest już częścią nowej gałęzi więc określ jego status" -#: rhodecode/model/validators.py:769 +#: kallithea/model/validators.py:836 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "Proszę podać poprawny adres IPv4 lub IPv6" -#: rhodecode/model/validators.py:770 -#, python-format -msgid "" -"The network size (bits) must be within the range of 0-32 (not %(bits)r)" +#: kallithea/model/validators.py:837 +#, python-format +msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" msgstr "Rozmiar sieci (bits) może mieścić się w zakresie od 0-32 (nie %(bits)r)" -#: rhodecode/model/validators.py:803 +#: kallithea/model/validators.py:870 msgid "Key name can only consist of letters, underscore, dash or numbers" -msgstr "Klucz nazwy może składać się tylko z liter, podkreślenia, myślnika lub numerów" - -#: rhodecode/model/validators.py:817 +msgstr "" +"Klucz nazwy może składać się tylko z liter, podkreślenia, myślnika lub " +"numerów" + +#: kallithea/model/validators.py:884 msgid "Filename cannot be inside a directory" msgstr "Nazwa pliku nie może znajdować się w katalogu" -#: rhodecode/templates/index.html:5 +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" +msgstr "" + +#: kallithea/templates/index.html:5 msgid "Dashboard" msgstr "Repozytorium" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/repo_switcher_list.html:4 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/users/user_edit_my_account.html:31 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/bookmarks/bookmarks.html:9 -#: rhodecode/templates/branches/branches.html:9 -#: rhodecode/templates/journal/journal.html:9 -#: rhodecode/templates/journal/journal.html:46 -#: rhodecode/templates/journal/journal.html:47 -#: rhodecode/templates/tags/tags.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 msgid "quick filter..." msgstr "szybki filtr..." -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/admin/repos/repos.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 msgid "repositories" msgstr "repozytoria" -#: rhodecode/templates/index_base.html:13 -#: rhodecode/templates/index_base.html:18 -#: rhodecode/templates/admin/repos/repo_add.html:5 -#: rhodecode/templates/admin/repos/repos.html:22 -msgid "Add repository" -msgstr "Dodaj repozytorium" - -#: rhodecode/templates/index_base.html:15 -#: rhodecode/templates/index_base.html:20 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:31 -msgid "Add group" -msgstr "Dodaj grupę" - -#: rhodecode/templates/index_base.html:27 -msgid "Edit group" -msgstr "Edytuj grupę" - -#: rhodecode/templates/index_base.html:27 +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" +msgstr "Dodaj Repozytorium" + +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "Dodaj Grupę Repozytoriów" + +#: kallithea/templates/index_base.html:32 msgid "You have admin right to this group, and can edit it" msgstr "Jako administrator uprawnienia tej grupy, i możesz je edytować" -#: rhodecode/templates/index_base.html:40 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:33 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:38 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:43 -#: rhodecode/templates/admin/users_groups/users_group_add.html:32 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 -#: rhodecode/templates/admin/users_groups/users_groups.html:37 -msgid "Group name" -msgstr "Nazwa grupy" - -#: rhodecode/templates/index_base.html:41 -#: rhodecode/templates/index_base.html:123 -#: rhodecode/templates/admin/repos/repo_add_base.html:56 -#: rhodecode/templates/admin/repos/repo_edit.html:68 -#: rhodecode/templates/admin/repos/repos.html:75 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:42 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:47 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:44 -#: rhodecode/templates/email_templates/changeset_comment.html:9 -#: rhodecode/templates/email_templates/pull_request.html:9 -#: rhodecode/templates/forks/fork.html:56 -#: rhodecode/templates/pullrequests/pullrequest.html:43 -#: rhodecode/templates/pullrequests/pullrequest_show.html:81 -#: rhodecode/templates/summary/summary.html:106 +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "Edytuj Grupę Repozytoriów" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" +msgstr "Nazwa Grupy" + +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 msgid "Description" msgstr "Opis" -#: rhodecode/templates/index_base.html:51 -#: rhodecode/templates/admin/permissions/permissions.html:55 -#: rhodecode/templates/admin/repos/repo_add_base.html:29 -#: rhodecode/templates/admin/repos/repo_edit.html:50 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:57 -#: rhodecode/templates/forks/fork.html:47 -msgid "Repository group" -msgstr "Repozytorium grupy" - -#: rhodecode/templates/index_base.html:121 -#: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit.html:32 -#: rhodecode/templates/admin/repos/repos.html:73 -#: rhodecode/templates/admin/users/user_edit_my_account.html:172 -#: rhodecode/templates/base/perms_summary.html:37 -#: rhodecode/templates/bookmarks/bookmarks.html:48 -#: rhodecode/templates/bookmarks/bookmarks_data.html:6 -#: rhodecode/templates/branches/branches.html:47 -#: rhodecode/templates/branches/branches_data.html:6 -#: rhodecode/templates/files/files_browser.html:47 -#: rhodecode/templates/journal/journal.html:193 -#: rhodecode/templates/journal/journal.html:283 -#: rhodecode/templates/summary/summary.html:55 -#: rhodecode/templates/summary/summary.html:124 -#: rhodecode/templates/tags/tags.html:48 -#: rhodecode/templates/tags/tags_data.html:6 +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 msgid "Name" msgstr "Nazwa" -#: rhodecode/templates/index_base.html:124 +#: kallithea/templates/index_base.html:129 msgid "Last Change" msgstr "Ostatnia akytwność" -#: rhodecode/templates/index_base.html:126 -#: rhodecode/templates/admin/repos/repos.html:76 -#: rhodecode/templates/admin/users/user_edit_my_account.html:174 -#: rhodecode/templates/journal/journal.html:195 -#: rhodecode/templates/journal/journal.html:285 +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 msgid "Tip" msgstr "Ostatnia zmiana" -#: rhodecode/templates/index_base.html:128 -#: rhodecode/templates/admin/repos/repo_edit.html:114 -#: rhodecode/templates/admin/repos/repos.html:78 +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 msgid "Owner" msgstr "Właściciel" -#: rhodecode/templates/index_base.html:136 -#: rhodecode/templates/admin/repos/repos.html:86 -#: rhodecode/templates/admin/users/user_edit_my_account.html:183 -#: rhodecode/templates/admin/users/users.html:107 -#: rhodecode/templates/bookmarks/bookmarks.html:74 -#: rhodecode/templates/branches/branches.html:73 -#: rhodecode/templates/journal/journal.html:204 -#: rhodecode/templates/journal/journal.html:294 -#: rhodecode/templates/tags/tags.html:74 +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 msgid "Click to sort ascending" msgstr "Kliknij, aby posortować rosnąco" -#: rhodecode/templates/index_base.html:137 -#: rhodecode/templates/admin/repos/repos.html:87 -#: rhodecode/templates/admin/users/user_edit_my_account.html:184 -#: rhodecode/templates/admin/users/users.html:108 -#: rhodecode/templates/bookmarks/bookmarks.html:75 -#: rhodecode/templates/branches/branches.html:74 -#: rhodecode/templates/journal/journal.html:205 -#: rhodecode/templates/journal/journal.html:295 -#: rhodecode/templates/tags/tags.html:75 +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 msgid "Click to sort descending" msgstr "Kliknij, aby posortować malejąco" -#: rhodecode/templates/index_base.html:138 +#: kallithea/templates/index_base.html:143 msgid "No repositories found." msgstr "Nie znaleziono repozytorium." -#: rhodecode/templates/index_base.html:139 -#: rhodecode/templates/admin/repos/repos.html:89 -#: rhodecode/templates/admin/users/user_edit_my_account.html:186 -#: rhodecode/templates/admin/users/users.html:110 -#: rhodecode/templates/bookmarks/bookmarks.html:77 -#: rhodecode/templates/branches/branches.html:76 -#: rhodecode/templates/journal/journal.html:207 -#: rhodecode/templates/journal/journal.html:297 -#: rhodecode/templates/tags/tags.html:77 +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 msgid "Data error." msgstr "Błąd danych." -#: rhodecode/templates/index_base.html:140 -#: rhodecode/templates/admin/repos/repos.html:90 -#: rhodecode/templates/admin/users/user_edit_my_account.html:58 -#: rhodecode/templates/admin/users/user_edit_my_account.html:187 -#: rhodecode/templates/admin/users/users.html:111 -#: rhodecode/templates/bookmarks/bookmarks.html:78 -#: rhodecode/templates/branches/branches.html:77 -#: rhodecode/templates/journal/journal.html:208 -#: rhodecode/templates/journal/journal.html:298 -#: rhodecode/templates/tags/tags.html:78 +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 msgid "Loading..." msgstr "Wczytywanie..." -#: rhodecode/templates/login.html:5 rhodecode/templates/base/base.html:239 +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 msgid "Log In" msgstr "Zaloguj się" -#: rhodecode/templates/login.html:21 +#: kallithea/templates/login.html:30 #, python-format msgid "Log In to %s" msgstr "Zaloguj się do %s" -#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20 -#: rhodecode/templates/admin/admin_log.html:5 -#: rhodecode/templates/admin/users/user_add.html:32 -#: rhodecode/templates/admin/users/user_edit.html:57 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:31 -#: rhodecode/templates/admin/users/users.html:77 -#: rhodecode/templates/base/base.html:215 -#: rhodecode/templates/summary/summary.html:123 +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 msgid "Username" msgstr "Nazwa użytkownika" -#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29 -#: rhodecode/templates/admin/ldap/ldap.html:46 -#: rhodecode/templates/admin/users/user_add.html:41 -#: rhodecode/templates/base/base.html:224 +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 msgid "Password" msgstr "Hasło" -#: rhodecode/templates/login.html:50 +#: kallithea/templates/login.html:62 msgid "Remember me" msgstr "Zapamiętaj mnie" -#: rhodecode/templates/login.html:54 +#: kallithea/templates/login.html:66 msgid "Sign In" msgstr "Zaloguj się" -#: rhodecode/templates/login.html:60 +#: kallithea/templates/login.html:72 msgid "Forgot your password ?" msgstr "Zapomniałeś hasła?" -#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:235 +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 msgid "Don't have an account ?" msgstr "Nie masz konta?" -#: rhodecode/templates/password_reset.html:5 +#: kallithea/templates/password_reset.html:5 msgid "Password Reset" msgstr "Łącze resetowania hasła" -#: rhodecode/templates/password_reset.html:11 -msgid "Reset your password to" -msgstr "Resetowanie hasła dla" - -#: rhodecode/templates/password_reset.html:21 -msgid "Email address" -msgstr "Adres e-mail" - -#: rhodecode/templates/password_reset.html:30 -msgid "Reset my password" -msgstr "Zresetuj swoje hasło" - -#: rhodecode/templates/password_reset.html:31 +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" +msgstr "Adres Email" + +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "" + +#: kallithea/templates/password_reset.html:64 msgid "Password reset link will be send to matching email address" msgstr "Link do zresetowania hasła zostanie wysłany na adres e-mail" -#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74 +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 msgid "Sign Up" msgstr "Zarejestruj się" -#: rhodecode/templates/register.html:11 -msgid "Sign Up to" -msgstr "Zarejestruj się do" - -#: rhodecode/templates/register.html:38 +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:58 msgid "Re-enter password" msgstr "Ponownie wprowadź hasło" -#: rhodecode/templates/register.html:47 -#: rhodecode/templates/admin/users/user_add.html:59 -#: rhodecode/templates/admin/users/user_edit.html:97 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:62 +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 msgid "First Name" msgstr "Imię" -#: rhodecode/templates/register.html:56 -#: rhodecode/templates/admin/users/user_add.html:68 -#: rhodecode/templates/admin/users/user_edit.html:106 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:71 +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 msgid "Last Name" msgstr "Nazwisko" -#: rhodecode/templates/register.html:65 -#: rhodecode/templates/admin/users/user_add.html:77 -#: rhodecode/templates/admin/users/user_edit.html:115 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:80 -#: rhodecode/templates/summary/summary.html:125 +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 msgid "Email" msgstr "E-mail" -#: rhodecode/templates/register.html:76 +#: kallithea/templates/register.html:108 msgid "Your account will be activated right after registration" msgstr "Twoje konto zostanie aktywowane zaraz po rejestracji" -#: rhodecode/templates/register.html:78 +#: kallithea/templates/register.html:110 msgid "Your account must wait for activation by administrator" msgstr "Twoje konto musi zostać aktywowane przez administratora" -#: rhodecode/templates/repo_switcher_list.html:10 -#: rhodecode/templates/admin/defaults/defaults.html:44 -#: rhodecode/templates/admin/repos/repo_add_base.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:78 -#: rhodecode/templates/data_table/_dt_elements.html:61 -#: rhodecode/templates/summary/summary.html:77 -msgid "Private repository" -msgstr "Prywatne repozytorium" - -#: rhodecode/templates/repo_switcher_list.html:12 -#: rhodecode/templates/data_table/_dt_elements.html:63 -#: rhodecode/templates/summary/summary.html:79 -msgid "Public repository" -msgstr "Publiczne repozytorium" - -#: rhodecode/templates/switch_to_list.html:10 -#: rhodecode/templates/branches/branches_data.html:57 +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 msgid "There are no branches yet" msgstr "Nie ma jeszcze gałęzi" -#: rhodecode/templates/switch_to_list.html:22 -#: rhodecode/templates/tags/tags_data.html:38 +#: kallithea/templates/switch_to_list.html:16 +msgid "Closed Branches" +msgstr "Zamknięte Gałęzie" + +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 msgid "There are no tags yet" msgstr "Nie ma jeszcze tagów" -#: rhodecode/templates/switch_to_list.html:35 -#: rhodecode/templates/bookmarks/bookmarks_data.html:37 +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 msgid "There are no bookmarks yet" msgstr "Nie ma jeszcze zakładek" -#: rhodecode/templates/admin/admin.html:5 -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/base/base.html:73 +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 msgid "Admin journal" msgstr "Dziennik administratora" -#: rhodecode/templates/admin/admin.html:10 +#: kallithea/templates/admin/admin.html:13 msgid "journal filter..." msgstr "szybkie wyszukiwanie..." -#: rhodecode/templates/admin/admin.html:12 -#: rhodecode/templates/journal/journal.html:11 +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 msgid "filter" msgstr "filtr" -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 #, python-format msgid "%s entry" msgid_plural "%s entries" @@ -1911,909 +2277,867 @@ msgstr[0] "%s wejście" msgstr[1] "%s wejść" msgstr[2] "%s wejść" -#: rhodecode/templates/admin/admin_log.html:6 -#: rhodecode/templates/admin/repos/repos.html:79 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46 -#: rhodecode/templates/admin/users/user_edit_my_account.html:176 -#: rhodecode/templates/admin/users/users.html:87 -#: rhodecode/templates/admin/users_groups/users_groups.html:40 -#: rhodecode/templates/journal/journal.html:197 -#: rhodecode/templates/journal/journal.html:287 +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 msgid "Action" msgstr "Działanie" -#: rhodecode/templates/admin/admin_log.html:7 -#: rhodecode/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" msgstr "Repozytorium" -#: rhodecode/templates/admin/admin_log.html:8 -#: rhodecode/templates/bookmarks/bookmarks.html:49 -#: rhodecode/templates/bookmarks/bookmarks_data.html:7 -#: rhodecode/templates/branches/branches.html:48 -#: rhodecode/templates/branches/branches_data.html:7 -#: rhodecode/templates/tags/tags.html:49 -#: rhodecode/templates/tags/tags_data.html:7 +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 msgid "Date" msgstr "Data" -#: rhodecode/templates/admin/admin_log.html:9 +#: kallithea/templates/admin/admin_log.html:9 msgid "From IP" msgstr "Z IP" -#: rhodecode/templates/admin/admin_log.html:63 +#: kallithea/templates/admin/admin_log.html:63 msgid "No actions yet" msgstr "Brak akcji" -#: rhodecode/templates/admin/defaults/defaults.html:5 -#: rhodecode/templates/admin/defaults/defaults.html:25 +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "Ustawienia Autentykacji" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "Autentykacja" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "Wtyczki Autentykacji" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "Włączone Wtyczki" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "" +"Comma separated list of plugins. Order of plugins is also order in which " +"Kallithea will try to authenticate user" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "Zapisz" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "Wtyczka" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 msgid "Repositories defaults" msgstr "Repozytoria domyślne" -#: rhodecode/templates/admin/defaults/defaults.html:11 -#: rhodecode/templates/base/base.html:80 +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 msgid "Defaults" msgstr "Domyślne" -#: rhodecode/templates/admin/defaults/defaults.html:35 -#: rhodecode/templates/admin/repos/repo_add_base.html:38 +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 msgid "Type" msgstr "Typ" -#: rhodecode/templates/admin/defaults/defaults.html:48 -#: rhodecode/templates/admin/repos/repo_add_base.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:82 -#: rhodecode/templates/forks/fork.html:69 +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "Prywatne repozytorium" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 msgid "" "Private repositories are only visible to people explicitly added as " "collaborators." -msgstr "Prywatne repozytoria są widoczne tylko dla osób bezpośrednio dodanych jako współpracownicy." - -#: rhodecode/templates/admin/defaults/defaults.html:55 -#: rhodecode/templates/admin/repos/repo_edit.html:87 +msgstr "" +"Prywatne repozytoria są widoczne tylko dla osób bezpośrednio dodanych " +"jako współpracownicy." + +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 msgid "Enable statistics" msgstr "Włącz statystyki" -#: rhodecode/templates/admin/defaults/defaults.html:59 -#: rhodecode/templates/admin/repos/repo_edit.html:91 +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." msgstr "Włącz okno statystyk na stronie podsumowania." -#: rhodecode/templates/admin/defaults/defaults.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:96 +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 msgid "Enable downloads" msgstr "Włącz pobieranie" -#: rhodecode/templates/admin/defaults/defaults.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:100 +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." msgstr "Włącz menu pobierania na stronie podsumowania." -#: rhodecode/templates/admin/defaults/defaults.html:75 -#: rhodecode/templates/admin/repos/repo_edit.html:105 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:64 +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 msgid "Enable locking" msgstr "Włącz blokowanie" -#: rhodecode/templates/admin/defaults/defaults.html:79 -#: rhodecode/templates/admin/repos/repo_edit.html:109 +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 msgid "Enable lock-by-pulling on repository." msgstr "Włącz blokowanie pobierania w repozytorium." -#: rhodecode/templates/admin/defaults/defaults.html:84 -#: rhodecode/templates/admin/ldap/ldap.html:89 -#: rhodecode/templates/admin/permissions/permissions.html:122 -#: rhodecode/templates/admin/repos/repo_edit.html:141 -#: rhodecode/templates/admin/repos/repo_edit.html:166 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:72 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:96 -#: rhodecode/templates/admin/settings/hooks.html:73 -#: rhodecode/templates/admin/users/user_add.html:94 -#: rhodecode/templates/admin/users/user_edit.html:140 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:88 -#: rhodecode/templates/admin/users_groups/users_group_add.html:49 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:143 -#: rhodecode/templates/base/default_perms_box.html:53 -msgid "Save" -msgstr "Zapisz" - -#: rhodecode/templates/admin/gists/index.html:5 -#: rhodecode/templates/base/base.html:299 -msgid "Gists" -msgstr "Git" - -#: rhodecode/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "Edytuj Gist" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "" +"Gist was update since you started editing. Copy your changes and click " +"%(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "Opis Gist ..." + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "Trwałość Gist" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "Wygasa" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "nigdy" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "zwykły" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "Zaktualizuj Gist" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "Anuluj" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 #, python-format msgid "Private Gists for user %s" -msgstr "Prywatne git użytkownika %s" - -#: rhodecode/templates/admin/gists/index.html:12 +msgstr "Prywatne Gists użytkownika %s" + +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 #, python-format msgid "Public Gists for user %s" -msgstr "Publiczne git użytkownika %s" - -#: rhodecode/templates/admin/gists/index.html:14 +msgstr "Publiczne Gists użytkownika %s" + +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 msgid "Public Gists" -msgstr "Publiczne git" - -#: rhodecode/templates/admin/gists/index.html:31 -#: rhodecode/templates/admin/gists/show.html:24 -#: rhodecode/templates/base/base.html:302 -msgid "Create new gist" -msgstr "Utwórz nowe git" - -#: rhodecode/templates/admin/gists/index.html:48 +msgstr "Publiczne Gists" + +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "Utwórz Nowy Gist" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 msgid "Created" msgstr "Utworzono" -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/index.html:53 -#: rhodecode/templates/admin/gists/show.html:43 -#: rhodecode/templates/admin/gists/show.html:45 -msgid "Expires" -msgstr "Wygasa" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/show.html:43 -msgid "never" -msgstr "nigdy" - -#: rhodecode/templates/admin/gists/index.html:68 +#: kallithea/templates/admin/gists/index.html:77 msgid "There are no gists yet" -msgstr "Nie ma jeszcze repozytorium git" - -#: rhodecode/templates/admin/gists/new.html:5 -#: rhodecode/templates/admin/gists/new.html:16 -msgid "New gist" -msgstr "Nowe git" - -#: rhodecode/templates/admin/gists/new.html:37 -msgid "Gist description ..." -msgstr "Opis git ..." - -#: rhodecode/templates/admin/gists/new.html:52 -msgid "Create private gist" -msgstr "Utwórz prywatne git" - -#: rhodecode/templates/admin/gists/new.html:53 -msgid "Create public gist" -msgstr "Utwórz publiczne git" - -#: rhodecode/templates/admin/gists/new.html:54 -#: rhodecode/templates/admin/permissions/permissions.html:123 -#: rhodecode/templates/admin/permissions/permissions.html:185 -#: rhodecode/templates/admin/repos/repo_edit.html:142 -#: rhodecode/templates/admin/repos/repo_edit.html:167 -#: rhodecode/templates/admin/repos/repo_edit.html:381 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:97 -#: rhodecode/templates/admin/settings/settings.html:115 -#: rhodecode/templates/admin/settings/settings.html:196 -#: rhodecode/templates/admin/settings/settings.html:288 -#: rhodecode/templates/admin/users/user_edit.html:141 -#: rhodecode/templates/admin/users/user_edit.html:198 -#: rhodecode/templates/admin/users/user_edit.html:246 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:89 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:144 -#: rhodecode/templates/base/default_perms_box.html:54 -#: rhodecode/templates/files/files_add.html:80 -#: rhodecode/templates/files/files_edit.html:66 -#: rhodecode/templates/pullrequests/pullrequest.html:86 +msgstr "Nie ma jeszcze żadnych gists" + +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "Nowy Gist" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "Utwórz Prywatny Gist" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "Utwórz Publiczny Gist" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 msgid "Reset" msgstr "Zresetuj" -#: rhodecode/templates/admin/gists/show.html:5 -msgid "gist" -msgstr "git" - -#: rhodecode/templates/admin/gists/show.html:9 +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 msgid "Gist" -msgstr "Git" - -#: rhodecode/templates/admin/gists/show.html:36 -msgid "Public gist" -msgstr "Publiczne git" - -#: rhodecode/templates/admin/gists/show.html:38 -msgid "Private gist" -msgstr "Prywatne git" - -#: rhodecode/templates/admin/gists/show.html:54 -#: rhodecode/templates/admin/repos/repo_edit.html:299 -#: rhodecode/templates/changeset/changeset_file_comment.html:40 +msgstr "Gist" + +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "Adres URL" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "Publiczny Gist" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "Prywatny Gist" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 msgid "Delete" msgstr "Usuń" -#: rhodecode/templates/admin/gists/show.html:54 -msgid "Confirm to delete this gist" -msgstr "Potwierdź usunięcie git" - -#: rhodecode/templates/admin/gists/show.html:63 -#: rhodecode/templates/admin/gists/show.html:84 -#: rhodecode/templates/files/files_edit.html:48 -#: rhodecode/templates/files/files_source.html:25 -#: rhodecode/templates/files/files_source.html:55 -msgid "Show as raw" -msgstr "wyświetl jako raw" - -#: rhodecode/templates/admin/gists/show.html:71 +#: kallithea/templates/admin/gists/show.html:59 +msgid "Confirm to delete this Gist" +msgstr "Potwierdź aby usunąć ten Gist" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "Edycja" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:76 msgid "created" msgstr "utworzono" -#: rhodecode/templates/admin/ldap/ldap.html:5 -msgid "LDAP administration" -msgstr "Administracja LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:11 -#: rhodecode/templates/admin/users/users.html:86 -#: rhodecode/templates/base/base.html:79 -msgid "LDAP" -msgstr "LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:28 -msgid "Connection settings" -msgstr "Ustawienia połączeń" - -#: rhodecode/templates/admin/ldap/ldap.html:30 -msgid "Enable LDAP" -msgstr "Włącz LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:34 -msgid "Host" -msgstr "Host" - -#: rhodecode/templates/admin/ldap/ldap.html:38 -msgid "Port" -msgstr "Port" - -#: rhodecode/templates/admin/ldap/ldap.html:42 -msgid "Account" -msgstr "Konto" - -#: rhodecode/templates/admin/ldap/ldap.html:50 -msgid "Connection security" -msgstr "Zabezpieczenie połączenia" - -#: rhodecode/templates/admin/ldap/ldap.html:54 -msgid "Certificate Checks" -msgstr "Kontrola certyfikatów" - -#: rhodecode/templates/admin/ldap/ldap.html:57 -msgid "Search settings" -msgstr "Ustawienia wyszukiwania" - -#: rhodecode/templates/admin/ldap/ldap.html:59 -msgid "Base DN" -msgstr "Bazowy DN" - -#: rhodecode/templates/admin/ldap/ldap.html:63 -msgid "LDAP Filter" -msgstr "Filtr LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:67 -msgid "LDAP Search Scope" -msgstr "Zakres wyszukiwania LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:70 -msgid "Attribute mappings" -msgstr "Mapowanie atrybutów" - -#: rhodecode/templates/admin/ldap/ldap.html:72 -msgid "Login Attribute" -msgstr "Atrybuty logowania" - -#: rhodecode/templates/admin/ldap/ldap.html:76 -msgid "First Name Attribute" -msgstr "Atrybut Nazwiska" - -#: rhodecode/templates/admin/ldap/ldap.html:80 -msgid "Last Name Attribute" -msgstr "Atrybut Imienia" - -#: rhodecode/templates/admin/ldap/ldap.html:84 -msgid "E-mail Attribute" -msgstr "Atrybut E-maila" - -#: rhodecode/templates/admin/notifications/notifications.html:5 -#: rhodecode/templates/admin/notifications/notifications.html:9 +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "wyświetl jako raw" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "Moje konto" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" +msgstr "Moje konto" + +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "Profil" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "Moje Emaile" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "Moje Repozytoria" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "Obserwowane" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "Połączone gałęzie" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "Moje uprawnienia" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "Dodaj" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "Główny" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "usuń" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "Potwierdź, aby usunąć ten e-mail: %s" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "Brak dodatkowych emaili" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "Nowy adres e-mail" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "Nowe hasło" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "Zmiana awataru na" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "Używa:" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "Avatary są wyłączone" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "" +"Your user is in an external Source of Record; some details cannot be " +"managed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "[zamknięty] wniosek o połączenie gałęzi" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "Otwarty przez mnie" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "Wniosek połączenia gałęzi #%s otwarty %s" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "Zamknięte" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "Potwierdź usunięcie połączenia gałęzi" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "Nic tu nie ma jeszcze" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "Biorę udział w" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "Wniosek połączenia gałęzi #%s otwarty %s dnia %s" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "Nie znaleziono rekordów." + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 msgid "My Notifications" msgstr "Opcje powiadomień" -#: rhodecode/templates/admin/notifications/notifications.html:29 +#: kallithea/templates/admin/notifications/notifications.html:32 msgid "All" msgstr "Wszystkie" -#: rhodecode/templates/admin/notifications/notifications.html:30 +#: kallithea/templates/admin/notifications/notifications.html:33 msgid "Comments" msgstr "Komentarze" -#: rhodecode/templates/admin/notifications/notifications.html:31 -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:8 -msgid "Pull requests" +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" msgstr "Połączone gałęzie" -#: rhodecode/templates/admin/notifications/notifications.html:35 +#: kallithea/templates/admin/notifications/notifications.html:38 msgid "Mark all read" msgstr "Oznacz wszystko jako przeczytane" -#: rhodecode/templates/admin/notifications/notifications_data.html:39 +#: kallithea/templates/admin/notifications/notifications_data.html:40 msgid "No notifications here yet" msgstr "Brak powiadomień" -#: rhodecode/templates/admin/notifications/show_notification.html:5 -#: rhodecode/templates/admin/notifications/show_notification.html:11 +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 msgid "Show notification" msgstr "Pokaż powiadomienia" -#: rhodecode/templates/admin/notifications/show_notification.html:9 -#: rhodecode/templates/base/base.html:253 +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 msgid "Notifications" msgstr "Powiadomienia" -#: rhodecode/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:5 msgid "Permissions administration" msgstr "Uprawnienia administracji" -#: rhodecode/templates/admin/permissions/permissions.html:11 -#: rhodecode/templates/admin/repos/repo_edit.html:151 -#: rhodecode/templates/admin/repos/repo_edit.html:158 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:81 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:88 -#: rhodecode/templates/admin/users/user_edit.html:150 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:129 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:136 -#: rhodecode/templates/base/base.html:78 +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 msgid "Permissions" msgstr "Uprawnienia" -#: rhodecode/templates/admin/permissions/permissions.html:24 -msgid "Default permissions" -msgstr "Domyślne uprawnienia" - -#: rhodecode/templates/admin/permissions/permissions.html:31 +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "Globalne" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "Lista dozwolonych adresów IP" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "Podgląd" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 msgid "Anonymous access" msgstr "Dostęp anonimowy" -#: rhodecode/templates/admin/permissions/permissions.html:49 +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without need to log in. Anonymous users use %s " +"user permissions" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 msgid "" "All default permissions on each repository will be reset to chosen " -"permission, note that all custom default permission on repositories will be " -"lost" -msgstr "Wszystkie uprawnienia domyślne każdego repozytorium zostaną przywrócone. Wybrane uprawnienie zostaną skasowane. Pamiętaj, że wszystkie niestandardowe uprawnienia w repozytoriach zostaną utracone." - -#: rhodecode/templates/admin/permissions/permissions.html:50 -#: rhodecode/templates/admin/permissions/permissions.html:63 -#: rhodecode/templates/admin/permissions/permissions.html:77 +"permission, note that all custom default permission on repositories will " +"be lost" +msgstr "" +"Wszystkie uprawnienia domyślne każdego repozytorium zostaną przywrócone. " +"Wybrane uprawnienie zostaną skasowane. Pamiętaj, że wszystkie " +"niestandardowe uprawnienia w repozytoriach zostaną utracone." + +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 msgid "Overwrite existing settings" msgstr "Nadpisz ustawienia" -#: rhodecode/templates/admin/permissions/permissions.html:62 +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "Repozytorium grupy" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 msgid "" "All default permissions on each repository group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" -msgstr "Wszystkie uprawnienia domyślne każdego repozytorium zostaną przywrócone. Wybrane uprawnienie zostaną skasowane. Pamiętaj, że wszystkie niestandardowe uprawnienia w repozytoriach zostaną utracone." - -#: rhodecode/templates/admin/permissions/permissions.html:69 +msgstr "" +"Wszystkie uprawnienia domyślne każdego repozytorium zostaną przywrócone. " +"Wybrane uprawnienie zostaną skasowane. Pamiętaj, że wszystkie " +"niestandardowe uprawnienia w repozytoriach zostaną utracone." + +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 msgid "User group" msgstr "Grupa użytkownika" -#: rhodecode/templates/admin/permissions/permissions.html:76 +#: kallithea/templates/admin/permissions/permissions_globals.html:53 msgid "" "All default permissions on each user group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" -msgstr "Wszystkie Uprawnienia domyślne każdej grupy użytkowników zostaną przywrócone do wybranego zezwolenia, trzeba pamiętać, że wszystkie niestandardowe uprawnienia domyślne dla grup repozytorium zostaną utracone" - -#: rhodecode/templates/admin/permissions/permissions.html:83 +msgstr "" +"Wszystkie Uprawnienia domyślne każdej grupy użytkowników zostaną " +"przywrócone do wybranego zezwolenia, trzeba pamiętać, że wszystkie " +"niestandardowe uprawnienia domyślne dla grup repozytorium zostaną " +"utracone" + +#: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" msgstr "Tworzenie repozytorium" -#: rhodecode/templates/admin/permissions/permissions.html:91 +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "" +"Write permission to repository groups allows creating repositories inside" +" that group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 msgid "User group creation" msgstr "Tworzenie grupy użytkowników" -#: rhodecode/templates/admin/permissions/permissions.html:99 +#: kallithea/templates/admin/permissions/permissions_globals.html:85 msgid "Repository forking" msgstr "Rozwidlanie repozytorium" -#: rhodecode/templates/admin/permissions/permissions.html:107 +#: kallithea/templates/admin/permissions/permissions_globals.html:93 msgid "Registration" msgstr "Rejestracja" -#: rhodecode/templates/admin/permissions/permissions.html:115 +#: kallithea/templates/admin/permissions/permissions_globals.html:101 msgid "External auth account activation" msgstr "Autoryzacja aktywacji zewnętrznego konta" -#: rhodecode/templates/admin/permissions/permissions.html:133 -msgid "Default User Permissions" -msgstr "Domyślne uprawnienia" - -#: rhodecode/templates/admin/permissions/permissions.html:144 -#: rhodecode/templates/admin/users/user_edit.html:207 -msgid "Allowed IP addresses" -msgstr "Adresy e-mail" - -#: rhodecode/templates/admin/permissions/permissions.html:158 -#: rhodecode/templates/admin/repos/repo_edit.html:340 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#: rhodecode/templates/admin/users/user_edit.html:175 -#: rhodecode/templates/admin/users/user_edit.html:220 -#: rhodecode/templates/admin/users_groups/users_groups.html:54 -#: rhodecode/templates/data_table/_dt_elements.html:122 -#: rhodecode/templates/data_table/_dt_elements.html:136 -msgid "delete" -msgstr "usuń" - -#: rhodecode/templates/admin/permissions/permissions.html:159 -#: rhodecode/templates/admin/users/user_edit.html:221 +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 #, python-format msgid "Confirm to delete this ip: %s" -msgstr "Potwierdź, aby usunąć ten e-mail: %s" - -#: rhodecode/templates/admin/permissions/permissions.html:165 -#: rhodecode/templates/admin/users/user_edit.html:227 +msgstr "Potwierdź, aby usunąć to ip: %s" + +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 msgid "All IP addresses are allowed" msgstr "Wszystkie adresy IP są dozwolone" -#: rhodecode/templates/admin/permissions/permissions.html:176 -#: rhodecode/templates/admin/users/user_edit.html:238 +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" msgstr "Nowy adres ip" -#: rhodecode/templates/admin/permissions/permissions.html:184 -#: rhodecode/templates/admin/repos/repo_add_base.html:73 -#: rhodecode/templates/admin/repos/repo_edit.html:380 -#: rhodecode/templates/admin/users/user_edit.html:197 -#: rhodecode/templates/admin/users/user_edit.html:245 -msgid "Add" -msgstr "Dodaj" - -#: rhodecode/templates/admin/repos/repo_add.html:12 -#: rhodecode/templates/admin/repos/repo_add.html:16 -#: rhodecode/templates/base/base.html:74 rhodecode/templates/base/base.html:88 -#: rhodecode/templates/base/base.html:116 -#: rhodecode/templates/base/base.html:275 -msgid "Repositories" -msgstr "Repozytoria" - -#: rhodecode/templates/admin/repos/repo_add.html:19 -msgid "Add new" -msgstr "Dodaj nowe" - -#: rhodecode/templates/admin/repos/repo_add_base.html:20 -#: rhodecode/templates/summary/summary.html:96 -#: rhodecode/templates/summary/summary.html:97 -msgid "Clone from" -msgstr "Klonuj z" - -#: rhodecode/templates/admin/repos/repo_add_base.html:24 -#: rhodecode/templates/admin/repos/repo_edit.html:45 -msgid "Optional http[s] url from which repository should be cloned." -msgstr "Opcjonalnie http[s] url z którego repozytorium powinno być klonowane." - -#: rhodecode/templates/admin/repos/repo_add_base.html:33 -#: rhodecode/templates/forks/fork.html:51 -msgid "Optionaly select a group to put this repository into." -msgstr "Opcjonalnie wybierz grupę do wprowadzenia tego repozytorium." - -#: rhodecode/templates/admin/repos/repo_add_base.html:42 -msgid "Type of repository to create." -msgstr "Rodzaj repozytorium do stworzenia." - -#: rhodecode/templates/admin/repos/repo_add_base.html:47 -#: rhodecode/templates/admin/repos/repo_edit.html:59 -#: rhodecode/templates/forks/fork.html:38 -msgid "Landing revision" -msgstr "Docelowa rewizja" - -#: rhodecode/templates/admin/repos/repo_add_base.html:51 -#: rhodecode/templates/admin/repos/repo_edit.html:63 -#: rhodecode/templates/forks/fork.html:42 -msgid "Default revision for files page, downloads, whoosh and readme" -msgstr "Wersja domyślna dla plików stronicowania, pobierania plików, readme" - -#: rhodecode/templates/admin/repos/repo_add_base.html:60 -#: rhodecode/templates/admin/repos/repo_edit.html:72 -#: rhodecode/templates/forks/fork.html:60 -msgid "" -"Keep it short and to the point. Use a README file for longer descriptions." -msgstr "Powinna być krótka i na temat. Użyj pliku README dla dłuższych opisów." - -#: rhodecode/templates/admin/repos/repo_edit.html:8 -msgid "Edit repository" -msgstr "Edytuj repozytorium" - -#: rhodecode/templates/admin/repos/repo_edit.html:12 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:11 -#: rhodecode/templates/base/base.html:81 -#: rhodecode/templates/base/base.html:134 -#: rhodecode/templates/summary/summary.html:212 +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "Repozytorium grupy" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "Repozytorium grupy" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "Nazwa grupy" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "Rodzic gropy" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "Grupy Repozytoriów" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 msgid "Settings" msgstr "Ustawienia" -#: rhodecode/templates/admin/repos/repo_edit.html:36 -msgid "Non-changeable id" -msgstr "Brak zmiennej id" - -#: rhodecode/templates/admin/repos/repo_edit.html:41 -msgid "Clone uri" -msgstr "Klonowane uri" - -#: rhodecode/templates/admin/repos/repo_edit.html:54 -msgid "Optional select a group to put this repository into." -msgstr "Opcjonalnie wybierz grupę do wprowadzenia tego repozytorium." - -#: rhodecode/templates/admin/repos/repo_edit.html:119 -msgid "Change owner of this repository." -msgstr "Zmiana właściciela tego repozytorium." - -#: rhodecode/templates/admin/repos/repo_edit.html:177 -msgid "Advanced settings" -msgstr "Zapisz ustawienia" - -#: rhodecode/templates/admin/repos/repo_edit.html:180 -msgid "Statistics" -msgstr "Statystyki" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Reset current statistics" -msgstr "Zresetuj bieżące statystyki" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Confirm to remove current statistics" -msgstr "Potwierdź usunięcie aktualnych statystyk" - -#: rhodecode/templates/admin/repos/repo_edit.html:187 -msgid "Fetched to rev" -msgstr "Ściągnięte do rev" - -#: rhodecode/templates/admin/repos/repo_edit.html:188 -msgid "Stats gathered" -msgstr "statystyki zgromadzone" - -#: rhodecode/templates/admin/repos/repo_edit.html:196 -msgid "Remote" -msgstr "Zdalnie" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Pull changes from remote location" -msgstr "Pobierz z zdalnej lokalizacji" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Confirm to pull changes from remote side" -msgstr "Potwierdź pull z zdalnej strony" - -#: rhodecode/templates/admin/repos/repo_edit.html:211 -msgid "Cache" -msgstr "Pamięć podręczna" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Invalidate repository cache" -msgstr "Unieważnij pamięć podręczną repozytorium" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Confirm to invalidate repository cache" -msgstr "Potwierdź unieważnienie pamięci podręcznej repozytorium" - -#: rhodecode/templates/admin/repos/repo_edit.html:218 -msgid "" -"Manually invalidate cache for this repository. On first access repository " -"will be cached again" -msgstr "Ręcznie unieważnienie cache dla tego repozytorium. Przy pierwszym dostępie do repozytorium zostanie dodany do bufora ponownie" - -#: rhodecode/templates/admin/repos/repo_edit.html:223 -msgid "List of cached values" -msgstr "Lista buforowanych wartości" - -#: rhodecode/templates/admin/repos/repo_edit.html:226 -msgid "Prefix" -msgstr "Prefiks" - -#: rhodecode/templates/admin/repos/repo_edit.html:227 -msgid "Key" -msgstr "Klucz" - -#: rhodecode/templates/admin/repos/repo_edit.html:228 -#: rhodecode/templates/admin/users/user_add.html:86 -#: rhodecode/templates/admin/users/user_edit.html:124 -#: rhodecode/templates/admin/users/users.html:84 -#: rhodecode/templates/admin/users_groups/users_group_add.html:41 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 -#: rhodecode/templates/admin/users_groups/users_groups.html:39 -msgid "Active" -msgstr "Aktywny" - -#: rhodecode/templates/admin/repos/repo_edit.html:243 -#: rhodecode/templates/base/base.html:292 -#: rhodecode/templates/base/base.html:293 -msgid "Public journal" -msgstr "Dziennik publiczny" - -#: rhodecode/templates/admin/repos/repo_edit.html:249 -msgid "Remove from public journal" -msgstr "Usuń z dziennika publicznego" - -#: rhodecode/templates/admin/repos/repo_edit.html:251 -msgid "Add to public journal" -msgstr "Dodaj do dziennika publicznego" - -#: rhodecode/templates/admin/repos/repo_edit.html:256 -msgid "" -"All actions made on this repository will be accessible to everyone in public" -" journal" -msgstr "Wszystkie działania wykonywane na tym repozytorium będą dostępne dla wszystkich w dzienniku publicznym" - -#: rhodecode/templates/admin/repos/repo_edit.html:263 -msgid "Locking" -msgstr "Blokuj" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Unlock locked repo" -msgstr "Odblokuj zablokowane repo" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Confirm to unlock repository" -msgstr "Potwierdź odblokowanie repozytorium" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Lock repo" -msgstr "Blokada repo" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Confirm to lock repository" -msgstr "Potwierdź blokowanie repozytorium" - -#: rhodecode/templates/admin/repos/repo_edit.html:272 -msgid "Repository is not locked" -msgstr "Repozytorium nie jest zablokowane" - -#: rhodecode/templates/admin/repos/repo_edit.html:277 -msgid "" -"Force locking on repository. Works only when anonymous access is disabled" -msgstr "Wymuś blokowanie na repozytorium. Działa tylko wtedy, gdy dostęp anonimowy jest wyłączony" - -#: rhodecode/templates/admin/repos/repo_edit.html:284 -msgid "Set as fork of" -msgstr "Ustaw jako rozwidlenie" - -#: rhodecode/templates/admin/repos/repo_edit.html:289 -msgid "Set" -msgstr "Ustaw" - -#: rhodecode/templates/admin/repos/repo_edit.html:293 -msgid "Manually set this repository as a fork of another from the list" -msgstr "Ręczne ustawienie rozwidlenia z listy" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Remove this repository" -msgstr "Usuń to repozytorium" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Confirm to delete this repository" -msgstr "Potwierdź, aby usunąć repozytorium" - -#: rhodecode/templates/admin/repos/repo_edit.html:310 -#, python-format -msgid "this repository has %s fork" -msgid_plural "this repository has %s forks" -msgstr[0] "to repozytorium ma %s fork" -msgstr[1] "to repozytorium ma %s forki" -msgstr[2] "to repozytorium ma %s forków" - -#: rhodecode/templates/admin/repos/repo_edit.html:311 -msgid "Detach forks" -msgstr "Ustaw jako rozwidlenie" - -#: rhodecode/templates/admin/repos/repo_edit.html:312 -msgid "Delete forks" -msgstr "Usuń rozwidlenie" - -#: rhodecode/templates/admin/repos/repo_edit.html:315 -msgid "" -"This repository will be renamed in a special way in order to be unaccesible " -"for RhodeCode and VCS systems. If you need to fully delete it from file " -"system please do it manually" -msgstr "To repozytorium zostanie zmienione w sposób szczególny, żeby było niedostępne dla strony i systemów VCS. Jeśli chcesz całkowicie usunąć go z systemu plików prosimy zrobić to ręcznie" - -#: rhodecode/templates/admin/repos/repo_edit.html:329 -msgid "Extra fields" -msgstr "Dodatkowe pola" - -#: rhodecode/templates/admin/repos/repo_edit.html:341 -#, python-format -msgid "Confirm to delete this field: %s" -msgstr "Potwierdź, aby usunąć ten e-mail: %s" - -#: rhodecode/templates/admin/repos/repo_edit.html:355 -msgid "New field key" -msgstr "Nowe pole klucza" - -#: rhodecode/templates/admin/repos/repo_edit.html:363 -msgid "New field label" -msgstr "Nowa etykieta pola" - -#: rhodecode/templates/admin/repos/repo_edit.html:366 -msgid "Enter short label" -msgstr "Wpisz krótką etykietę" - -#: rhodecode/templates/admin/repos/repo_edit.html:372 -msgid "New field description" -msgstr "Nowy opis pola" - -#: rhodecode/templates/admin/repos/repo_edit.html:375 -msgid "Enter description of a field" -msgstr "Wprowadź opis pola" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:3 -msgid "none" -msgstr "brak" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:4 -msgid "read" -msgstr "odczyt" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:5 -msgid "write" -msgstr "zapis" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:6 -msgid "admin" -msgstr "administracja" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:7 -msgid "member" -msgstr "użytkownik" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:16 -msgid "private repository" -msgstr "prywatne repozytorium" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:19 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:28 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:20 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:35 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:20 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:35 -msgid "default" -msgstr "domyślne" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:33 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:58 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:25 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:55 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:25 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:55 -msgid "revoke" -msgstr "odwołane" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:83 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:81 -msgid "Add another member" -msgstr "Dodaj kolejnego użytkownika" - -#: rhodecode/templates/admin/repos/repos.html:5 -msgid "Repositories administration" -msgstr "Administracja repozytoriami" - -#: rhodecode/templates/admin/repos/repos.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account.html:185 -#: rhodecode/templates/admin/users/users.html:109 -#: rhodecode/templates/bookmarks/bookmarks.html:76 -#: rhodecode/templates/branches/branches.html:75 -#: rhodecode/templates/journal/journal.html:206 -#: rhodecode/templates/journal/journal.html:296 -#: rhodecode/templates/tags/tags.html:76 -msgid "No records found." -msgstr "Nie znaleziono rekordów." - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:87 -msgid "apply to children" -msgstr "dotyczy dzieci" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:88 -msgid "" -"Set or revoke permission to all children of that group, including non-" -"private repositories and other groups" -msgstr "Ustawia lub cofa uprawnienia do wszystkich dzieci z tej grupy, w tym repozytoria oraz innych grup" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:4 -#, python-format -msgid "%s Group Dashboard" -msgstr "%s Grupa" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:9 -msgid "Home" -msgstr "Strona Główna" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:13 -msgid "with" -msgstr "używając" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5 -msgid "Add repository group" -msgstr "Repozytorium grupy" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:16 -#: rhodecode/templates/base/base.html:75 rhodecode/templates/base/base.html:91 -msgid "Repository groups" -msgstr "Repozytorium grupy" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:13 -msgid "Add new repository group" -msgstr "Dodaj nową grupę repozytorium" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:51 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:56 -msgid "Group parent" -msgstr "Rodzic gropy" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:59 -msgid "save" -msgstr "zapisz" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5 -msgid "Edit repository group" -msgstr "Edytuj grupy repozytorium" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:13 -#, python-format -msgid "Edit repository group %s" -msgstr "Edytuj grupę repozytorium %s" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:27 -msgid "Add child group" -msgstr "Dodaj dzieci grup" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:68 -msgid "" -"Enable lock-by-pulling on group. This option will be applied to all other " -"groups and repositories inside" -msgstr "Włącz blokowanie pobierania przez grupy. Opcja ta będzie stosowana do wszystkich innych grup i repozytoriów wewnątrz" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5 -msgid "Repository groups administration" -msgstr "Repozytoria grup administracyjnych" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:45 -msgid "Number of toplevel repositories" -msgstr "Liczba najwyższego poziomu repozytorium" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:64 -#: rhodecode/templates/admin/users_groups/users_groups.html:48 -#: rhodecode/templates/changeset/changeset_file_comment.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:171 -msgid "Edit" -msgstr "Edycja" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:65 -#: rhodecode/templates/admin/users_groups/users_groups.html:49 -#: rhodecode/templates/base/perms_summary.html:29 -#: rhodecode/templates/base/perms_summary.html:60 -#: rhodecode/templates/base/perms_summary.html:62 -#: rhodecode/templates/data_table/_dt_elements.html:116 -#: rhodecode/templates/data_table/_dt_elements.html:117 -#: rhodecode/templates/data_table/_dt_elements.html:130 -#: rhodecode/templates/data_table/_dt_elements.html:131 -msgid "edit" -msgstr "edycja" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" +msgstr "Zaawansowane" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "Grupa Repozytoriów: %s" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "Ogólna liczba repozytoriów" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "Utworzono" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 #, python-format msgid "Confirm to delete this group: %s with %s repository" msgid_plural "Confirm to delete this group: %s with %s repositories" @@ -2821,944 +3145,1617 @@ msgstr[0] "Potwierdź żeby usunąć grupę %s wraz z %s repozytorium" msgstr[1] "Potwierdź żeby usunąć grupę %s wraz z %s repozytoriami" msgstr[2] "Potwierdź żeby usunąć grupę %s wraz z %s repozytoriami" -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:78 -msgid "There are no repository groups yet" -msgstr "Nie ma jeszcze grup repozytoriów" - -#: rhodecode/templates/admin/settings/hooks.html:5 -#: rhodecode/templates/admin/settings/settings.html:5 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "Usuń ta grupę repozytoriów" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "brak" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "odczyt" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "zapis" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "administracja" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "użytkownik/grupa użytkowników" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "domyślny" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "odwołane" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "Dodaj nowe" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "dotyczy dzieci" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "Oba" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "" +"Set or revoke permission to all children of that group, including non-" +"private repositories and other groups if selected." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "" +"Enable lock-by-pulling on group. This option will be applied to all other" +" groups and repositories inside" +msgstr "" +"Włącz blokowanie pobierania przez grupy. Opcja ta będzie stosowana do " +"wszystkich innych grup i repozytoriów wewnątrz" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "%s Repository group dashboard" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "Strona Główna" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "używając" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "Repozytoria grup administracyjnych" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "Liczba najwyższego poziomu repozytorium" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "Dodaj repozytorium" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "Klonuj z" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "Opcjonalnie http[s] url z którego repozytorium powinno być klonowane." + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "Powinna być krótka i na temat. Użyj pliku README dla dłuższych opisów." + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "Opcjonalnie wybierz grupę do wprowadzenia tego repozytorium." + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "Rodzaj repozytorium do stworzenia." + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "Docelowa rewizja" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is beeing created, you will be redirected " +"when this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:42 +msgid "" +"We're sorry but error occured during this operation. Please check your " +"Kallithea server logs, or contact administrator." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, python-format +msgid "%s repository settings" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "Dodatkowe pola" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +msgid "Remote" +msgstr "Zdalnie" + +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "Statystyki" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "Gałąź z" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "Ustaw" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "Ręczne ustawienie rozwidlenia z listy" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Remove from public journal" +msgstr "Usuń z dziennika publicznego" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +msgid "Add to public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 +msgid "" +"All actions made on this repository will be accessible to everyone in " +"public journal" +msgstr "" +"Wszystkie działania wykonywane na tym repozytorium będą dostępne dla " +"wszystkich w dzienniku publicznym" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 +msgid "Confirm to unlock repository" +msgstr "Potwierdź odblokowanie repozytorium" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 +msgid "Confirm to lock repository" +msgstr "Potwierdź blokowanie repozytorium" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 +msgid "Repository is not locked" +msgstr "Repozytorium nie jest zablokowane" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 +msgid "" +"Force locking on repository. Works only when anonymous access is " +"disabled. Trigering a pull locks repository by user who pulled, only the " +"same user can unlock by doing a push" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "Potwierdź usunięcie repozytorium: %s" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +msgid "Delete this repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 +#, python-format +msgid "this repository has %s fork" +msgid_plural "this repository has %s forks" +msgstr[0] "to repozytorium ma %s fork" +msgstr[1] "to repozytorium ma %s forki" +msgstr[2] "to repozytorium ma %s forków" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 +msgid "Detach forks" +msgstr "Ustaw jako rozwidlenie" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 +msgid "Delete forks" +msgstr "Usuń rozwidlenie" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "" +"This repository will be renamed in a special way in order to be " +"unaccesible for Kallithea and VCS systems. If you need to fully delete it" +" from file system please do it manually" +msgstr "" +"To repozytorium zostanie zmienione w sposób szczególny, żeby było " +"niedostępne dla strony i systemów VCS. Jeśli chcesz całkowicie usunąć go " +"z systemu plików prosimy zrobić to ręcznie" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "Unieważnij pamięć podręczną repozytorium" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "Potwierdź unieważnienie pamięci podręcznej repozytorium" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 +msgid "" +"Manually invalidate cache for this repository. On first access repository" +" will be cached again" +msgstr "" +"Ręcznie unieważnienie cache dla tego repozytorium. Przy pierwszym " +"dostępie do repozytorium zostanie dodany do bufora ponownie" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "Lista buforowanych wartości" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "Prefiks" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "Klucz" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "Aktywny" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#, python-format +msgid "Confirm to delete this field: %s" +msgstr "Potwierdź, aby usunąć to pole: %s" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 +msgid "New field key" +msgstr "Nowe pole klucza" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 +msgid "New field label" +msgstr "Nowa etykieta pola" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 +msgid "Enter short label" +msgstr "Wpisz krótką etykietę" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 +msgid "New field description" +msgstr "Nowy opis pola" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +msgid "Enter description of a field" +msgstr "Wprowadź opis pola" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 +msgid "private repository" +msgstr "prywatne repozytorium" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "Pobierz z zdalnej lokalizacji" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "Potwierdź pull z zdalnej strony" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "Brak zmiennej id" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 +msgid "" +"In case this repository is renamed or moved into another group the " +"repository url changes.\n" +" Using above url guarantees that this " +"repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases" +" that you need to hardcode the url into 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "Klonowane uri" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "edycja" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "Opcjonalnie wybierz grupę do wprowadzenia tego repozytorium." + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "Wersja domyślna dla plików stronicowania, pobierania plików, readme" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "Zmiana właściciela tego repozytorium." + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "Potwierdź usunięcie aktualnych statystyk" + +#: kallithea/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "Administracja repozytoriami" + +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 msgid "Settings administration" msgstr "Ustawienia administracji" -#: rhodecode/templates/admin/settings/hooks.html:24 -msgid "Built in hooks - read only" -msgstr "Wbudowana w aktualizację - tylko do odczytu" - -#: rhodecode/templates/admin/settings/hooks.html:40 -msgid "Custom hooks" -msgstr "Niestandardowa aktualizacja" - -#: rhodecode/templates/admin/settings/hooks.html:56 -msgid "remove" -msgstr "usuń" - -#: rhodecode/templates/admin/settings/hooks.html:88 -msgid "Failed to remove hook" -msgstr "Nie udało się usunąć hooka" - -#: rhodecode/templates/admin/settings/settings.html:26 -msgid "Remap and rescan repositories" -msgstr "Mapowanie i skanowanie repozytorów" - -#: rhodecode/templates/admin/settings/settings.html:34 -msgid "Rescan option" -msgstr "ponowne skanowanie opcji" - -#: rhodecode/templates/admin/settings/settings.html:40 -msgid "" -"In case a repository was deleted from filesystem and there are leftovers in " -"the database check this option to scan obsolete data in database and remove " -"it." -msgstr "W przypadku repozytoriów zostaną usunięte systemy plików i jeśli są pozostałości w bazie danych to ta opcja sprawdzi ją oraz przeskanuje, a następnie usunie je z bazy danych." - -#: rhodecode/templates/admin/settings/settings.html:41 -msgid "Destroy old data" -msgstr "Zniszcz stare dane" - -#: rhodecode/templates/admin/settings/settings.html:43 -msgid "" -"Rescan repositories location for new repositories. Also deletes obsolete if " -"`destroy` flag is checked " -msgstr "Skanowanie ponowne lokalizacji dla nowych repozytoriów. Usuwa również nieaktualne jeśli została zaznaczona flaga `zniszcz` do sprawdzana" - -#: rhodecode/templates/admin/settings/settings.html:48 -msgid "Rescan repositories" -msgstr "Skanuj ponownie repozytoria" - -#: rhodecode/templates/admin/settings/settings.html:54 -msgid "Whoosh indexing" -msgstr "indeksowanie Whoosh" - -#: rhodecode/templates/admin/settings/settings.html:62 -msgid "Index build option" -msgstr "opcja budowania indeksowania" - -#: rhodecode/templates/admin/settings/settings.html:67 -msgid "Build from scratch" -msgstr "buduj od podstaw" - -#: rhodecode/templates/admin/settings/settings.html:73 -msgid "Reindex" -msgstr "Indeksuj ponownie" - -#: rhodecode/templates/admin/settings/settings.html:79 -msgid "Global application settings" -msgstr "Globalne ustawienia aplikacji" - -#: rhodecode/templates/admin/settings/settings.html:88 +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "Aktualizacja" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:16 +msgid "SMTP auth" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:39 +msgid "Send" +msgstr "Wyślij" + +#: kallithea/templates/admin/settings/settings_global.html:8 msgid "Site branding" msgstr "Nazwa strony" -#: rhodecode/templates/admin/settings/settings.html:97 +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:18 msgid "HTTP authentication realm" msgstr "Sfera uwierzytelniania HTTP" -#: rhodecode/templates/admin/settings/settings.html:106 +#: kallithea/templates/admin/settings/settings_global.html:27 msgid "Google Analytics code" msgstr "Kod Google Analytics" -#: rhodecode/templates/admin/settings/settings.html:114 -#: rhodecode/templates/admin/settings/settings.html:195 -#: rhodecode/templates/admin/settings/settings.html:287 +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:50 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 msgid "Save settings" msgstr "Zapisz ustawienia" -#: rhodecode/templates/admin/settings/settings.html:121 -msgid "Visualisation settings" -msgstr "Ustawienia wizualizacji" - -#: rhodecode/templates/admin/settings/settings.html:129 -msgid "General" -msgstr "Główne" - -#: rhodecode/templates/admin/settings/settings.html:134 -msgid "Use repository extra fields" -msgstr "Używaj w repozytorium dodatkowych pól" - -#: rhodecode/templates/admin/settings/settings.html:136 -msgid "Allows storing additional customized fields per repository." -msgstr "Umożliwia przechowywanie dodatkowych niestandardowych pól w repozytorium." - -#: rhodecode/templates/admin/settings/settings.html:139 -msgid "Show RhodeCode version" -msgstr "Pokaż wersję RhodeCode" - -#: rhodecode/templates/admin/settings/settings.html:141 -msgid "Shows or hides displayed version of RhodeCode in the footer" -msgstr "Pokazuje lub ukrywa wyświetlaną wersję RhodeCode w stopce" - -#: rhodecode/templates/admin/settings/settings.html:146 -msgid "Dashboard items" -msgstr "Pozycja panelu" - -#: rhodecode/templates/admin/settings/settings.html:150 +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "" +"Hooks can be used to trigger actions on certain events such as push / " +"pull. They can trigger Python functions or external applications." +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 +msgid "Custom hooks" +msgstr "Niestandardowa aktualizacja" + +#: kallithea/templates/admin/settings/settings_hooks.html:69 +msgid "Failed to remove hook" +msgstr "Nie udało się usunąć hooka" + +#: kallithea/templates/admin/settings/settings_mapping.html:6 +msgid "Rescan option" +msgstr "ponowne skanowanie opcji" + +#: kallithea/templates/admin/settings/settings_mapping.html:11 +msgid "Destroy old data" +msgstr "Zniszcz stare dane" + +#: kallithea/templates/admin/settings/settings_mapping.html:13 +msgid "" +"In case a repository was deleted from filesystem and it still exists in " +"the database check this option to scan obsolete data in database and " +"remove it." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "Unieważnia cache dla wszystkich repozytoriów" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 +msgid "" +"Each cache data for repositories will be cleaned with this option " +"selected. Use this to reload data and clear cache keys." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 msgid "" -"Number of items displayed in lightweight dashboard before pagination is " -"shown." -msgstr "Liczba elementów wyświetlanych w lekkim panelu z podziałem na strony." - -#: rhodecode/templates/admin/settings/settings.html:155 -msgid "Icons" -msgstr "Ikony" - -#: rhodecode/templates/admin/settings/settings.html:160 -msgid "Show public repo icon on repositories" -msgstr "Pokazuj w publicznym repo ikonę w repozytoriach" - -#: rhodecode/templates/admin/settings/settings.html:164 -msgid "Show private repo icon on repositories" -msgstr "Pokazuj w prywatnym repo ikonę w repozytoriach" - -#: rhodecode/templates/admin/settings/settings.html:166 -msgid "Show public/private icons next to repositories names" -msgstr "Pokazuj w publicznych/prywatnych repozytoriach ikony obok nazw" - -#: rhodecode/templates/admin/settings/settings.html:172 -msgid "Meta-Tagging" -msgstr "Tagowanie meta" - -#: rhodecode/templates/admin/settings/settings.html:177 -msgid "Stylify recognised metatags:" -msgstr "Stylizacja rozpoznanych meta tagów:" - -#: rhodecode/templates/admin/settings/settings.html:204 -msgid "VCS settings" -msgstr "VCS ustawienia" - -#: rhodecode/templates/admin/settings/settings.html:213 +"Verify if Kallitheas GIT hooks are installed for each repository. Current" +" hooks will be updated to latest version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:7 +msgid "Index build option" +msgstr "Opcja odbudowy indeksowania" + +#: kallithea/templates/admin/settings/settings_search.html:12 +msgid "Build from scratch" +msgstr "Buduj od podstaw" + +#: kallithea/templates/admin/settings/settings_search.html:15 +msgid "" +"This option completely reindex all the files within Kallithea for proper " +"fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:21 +msgid "Reindex" +msgstr "Indeksuj ponownie" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 msgid "Web" msgstr "www" -#: rhodecode/templates/admin/settings/settings.html:218 +#: kallithea/templates/admin/settings/settings_vcs.html:11 msgid "Require SSL for vcs operations" msgstr "Wymagaj ssl dla operacji vcs" -#: rhodecode/templates/admin/settings/settings.html:220 +#: kallithea/templates/admin/settings/settings_vcs.html:13 msgid "" -"RhodeCode will require SSL for pushing or pulling. If SSL is missing it will" -" return HTTP Error 406: Not Acceptable" -msgstr "RhodeCode wymaga SSL do wysłania zmian lub pobierania. Jeśli brakuje SSL zwróci błąd HTTP 406: Not Acceptable" - -#: rhodecode/templates/admin/settings/settings.html:226 -msgid "Hooks" -msgstr "Aktualizacja" - -#: rhodecode/templates/admin/settings/settings.html:231 -msgid "Update repository after push (hg update)" -msgstr "Aktualizacja repozytorium po wysłaniu zmian (aktualizacja hg)" - -#: rhodecode/templates/admin/settings/settings.html:235 +"Activate to set Kallithea to require SSL for pushing or pulling. If SSL " +"certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 msgid "Show repository size after push" msgstr "Pokaż rozmiar repozytorium po wysłaniu zmian" -#: rhodecode/templates/admin/settings/settings.html:239 +#: kallithea/templates/admin/settings/settings_vcs.html:28 msgid "Log user push commands" msgstr "Logi poleceń wysłania zmian użytkowników" -#: rhodecode/templates/admin/settings/settings.html:243 +#: kallithea/templates/admin/settings/settings_vcs.html:32 msgid "Log user pull commands" msgstr "Logi poleceń połączenia gałęzi użytkowników" -#: rhodecode/templates/admin/settings/settings.html:247 -msgid "Advanced setup" -msgstr "Zaawansowane ustawienia" - -#: rhodecode/templates/admin/settings/settings.html:252 +#: kallithea/templates/admin/settings/settings_vcs.html:36 +msgid "Update repository after push (hg update)" +msgstr "Aktualizacja repozytorium po wysłaniu zmian (aktualizacja hg)" + +#: kallithea/templates/admin/settings/settings_vcs.html:42 msgid "Mercurial Extensions" msgstr "Rozszerzenia Mercurial" -#: rhodecode/templates/admin/settings/settings.html:257 +#: kallithea/templates/admin/settings/settings_vcs.html:47 msgid "Enable largefiles extension" msgstr "Rozszerzenia dużych pliów" -#: rhodecode/templates/admin/settings/settings.html:261 +#: kallithea/templates/admin/settings/settings_vcs.html:51 msgid "Enable hgsubversion extension" msgstr "Rozszerzenia hgsubversion" -#: rhodecode/templates/admin/settings/settings.html:263 +#: kallithea/templates/admin/settings/settings_vcs.html:53 msgid "" -"Requires hgsubversion library installed. Allows cloning from svn remote " -"locations" -msgstr "Wymaga biblioteki hgsubversion zainstalowanej. Umożliwia klonowanie z zdalnych lokalizacji svn" - -#: rhodecode/templates/admin/settings/settings.html:274 +"Requires hgsubversion library to be installed. Allows cloning remote SVN " +"repositories and migrates them to Mercurial type." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 msgid "Repositories location" msgstr "Położenie repozytorium" -#: rhodecode/templates/admin/settings/settings.html:279 +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting" +" take effect." +msgstr "" +"Kliknij, aby odblokować. Musisz ponownie uruchomić Kallithea żeby " +"wprowadzić to ustawienie w życie." + +#: kallithea/templates/admin/settings/settings_vcs.html:72 msgid "" -"Click to unlock. You must restart RhodeCode in order to make this setting " -"take effect." -msgstr "Kliknij, aby odblokować. Musisz ponownie uruchomić RhodeCode żeby wprowadzić to ustawienie w życie." - -#: rhodecode/templates/admin/settings/settings.html:280 -#: rhodecode/templates/base/base.html:143 -msgid "Unlock" -msgstr "Odblokowany" - -#: rhodecode/templates/admin/settings/settings.html:282 +"Filesystem location where repositories should be stored. After changing " +"this value a restart and rescan of the repository folder are required." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:8 +msgid "General" +msgstr "Główne" + +#: kallithea/templates/admin/settings/settings_visual.html:13 +msgid "Use repository extra fields" +msgstr "Używaj w repozytorium dodatkowych pól" + +#: kallithea/templates/admin/settings/settings_visual.html:15 +msgid "Allows storing additional customized fields per repository." +msgstr "Umożliwia przechowywanie dodatkowych niestandardowych pól w repozytorium." + +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "Pokaż wersję Kallithea" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:30 +msgid "" +"Gravatar url allows you to use other avatar server application.\n" +" Following " +"variables of the URL will be replaced accordingly.\n" +" {scheme} " +"'http' or 'https' sent from running Kallithea server,\n" +" {email} user " +"email,\n" +" {md5email} md5 " +"hash of the user email (like at gravatar.com),\n" +" {size} size " +"of the image that is expected from the server application,\n" +" {netloc} " +"network location/server host of running Kallithea server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:42 msgid "" -"Location where repositories are stored. After changing this value a restart," -" and rescan is required" -msgstr "Miejsce, w którym przechowywane są repozytoria. Po zmianie tej wartości jest wymagany restart i ponowne skanowanie" - -#: rhodecode/templates/admin/settings/settings.html:303 -msgid "Test Email" -msgstr "Test e-maila" - -#: rhodecode/templates/admin/settings/settings.html:311 -msgid "Email to" -msgstr "E-mail do" - -#: rhodecode/templates/admin/settings/settings.html:319 -msgid "Send" -msgstr "Wyślij" - -#: rhodecode/templates/admin/settings/settings.html:325 -msgid "System Info and Packages" -msgstr "Informacje Systemowe i pakiety" - -#: rhodecode/templates/admin/settings/settings.html:328 -#: rhodecode/templates/changelog/changelog.html:51 -msgid "Show" -msgstr "Wyświetl" - -#: rhodecode/templates/admin/users/user_add.html:5 -msgid "Add user" -msgstr "Dodaj użytkownika" - -#: rhodecode/templates/admin/users/user_add.html:10 -#: rhodecode/templates/admin/users/user_edit.html:11 -#: rhodecode/templates/base/base.html:76 -msgid "Users" -msgstr "Użytkownicy" - -#: rhodecode/templates/admin/users/user_add.html:12 -#: rhodecode/templates/admin/users/users.html:23 -msgid "Add new user" -msgstr "Dodaj nowego użytkownika" - -#: rhodecode/templates/admin/users/user_add.html:50 -msgid "Password confirmation" -msgstr "Potwierdzenie hasła" - -#: rhodecode/templates/admin/users/user_edit.html:5 -msgid "Edit user" -msgstr "Edytuj użytkownika" - -#: rhodecode/templates/admin/users/user_edit.html:13 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 -#, python-format -msgid "Edit %s" -msgstr "Edycja %s" - -#: rhodecode/templates/admin/users/user_edit.html:34 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:10 -msgid "Change your avatar at" -msgstr "Zmiana awataru na" - -#: rhodecode/templates/admin/users/user_edit.html:35 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:11 -msgid "Using" -msgstr "Używa:" - -#: rhodecode/templates/admin/users/user_edit.html:43 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:20 -msgid "API key" -msgstr "Klucz API" - -#: rhodecode/templates/admin/users/user_edit.html:50 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:25 -msgid "Current IP" -msgstr "Obecny IP" - -#: rhodecode/templates/admin/users/user_edit.html:70 -msgid "LDAP DN" -msgstr "LDAP DN" - -#: rhodecode/templates/admin/users/user_edit.html:79 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:44 -msgid "New password" -msgstr "Nowe hasło" - -#: rhodecode/templates/admin/users/user_edit.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:53 -msgid "New password confirmation" -msgstr "Potwierdzenie nowego hasła" - -#: rhodecode/templates/admin/users/user_edit.html:163 -msgid "Email addresses" -msgstr "Adresy e-mail" - -#: rhodecode/templates/admin/users/user_edit.html:176 -#, python-format -msgid "Confirm to delete this email: %s" -msgstr "Potwierdź, aby usunąć ten e-mail: %s" - -#: rhodecode/templates/admin/users/user_edit.html:190 -msgid "New email address" -msgstr "Nowy adres e-mail" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:5 -#: rhodecode/templates/base/base.html:254 -msgid "My account" -msgstr "Moje konto" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:9 -msgid "My Account" -msgstr "Moje konto" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:35 -msgid "My permissions" -msgstr "Moje uprawnienia" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:38 -#: rhodecode/templates/journal/journal.html:54 -msgid "My repos" -msgstr "Moje repo" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:41 -msgid "My pull requests" -msgstr "Moje prośby połączenia gałęzi" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:4 -msgid "Show closed pull requests" -msgstr "[zamknięty] wniosek o połączenie gałęzi" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:6 -msgid "Opened by me" -msgstr "Otwarty przez mnie" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "Wniosek połączenia gałęzi #%s otwarty %s" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:17 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:45 -#: rhodecode/templates/pullrequests/pullrequest_data.html:11 -#: rhodecode/templates/pullrequests/pullrequest_show.html:27 -#: rhodecode/templates/pullrequests/pullrequest_show.html:42 -msgid "Closed" -msgstr "Zamknięte" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:23 -msgid "Confirm to delete this pull request" -msgstr "Potwierdź usunięcie połączenia gałęzi" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:30 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:51 -msgid "Nothing here yet" -msgstr "Nic tu nie ma jeszcze" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:34 -msgid "I participate in" -msgstr "Biorę udział w" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:42 -#: rhodecode/templates/pullrequests/pullrequest_data.html:8 -#, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "Wniosek połączenia gałęzi #%s otwarty %s dnia %s" - -#: rhodecode/templates/admin/users/users.html:5 -msgid "Users administration" -msgstr "Administracja użytkownikami" - -#: rhodecode/templates/admin/users/users.html:9 -msgid "users" -msgstr "użytkownicy" - -#: rhodecode/templates/admin/users/users.html:80 -msgid "Firstname" -msgstr "imię" - -#: rhodecode/templates/admin/users/users.html:81 -msgid "Lastname" -msgstr "nazwisko" - -#: rhodecode/templates/admin/users/users.html:82 -msgid "Last login" -msgstr "Ostatnio zalogowany" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:5 +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}'," +" available vars:\n" +" {scheme} 'http' " +"or 'https' sent from running Kallithea server,\n" +" {user} current " +"user username,\n" +" {netloc} network " +"location/server host of running Kallithea server,\n" +" {repo} full " +"repository name,\n" +" {repoid} ID of " +"repository, can be used to contruct clone-by-id" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:54 +msgid "Dashboard items" +msgstr "Pozycja panelu" + +#: kallithea/templates/admin/settings/settings_visual.html:58 +msgid "" +"Number of items displayed in the main page dashboard before pagination is" +" shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:68 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:74 +msgid "Icons" +msgstr "Ikony" + +#: kallithea/templates/admin/settings/settings_visual.html:79 +msgid "Show public repo icon on repositories" +msgstr "Pokazuj w publicznym repo ikonę w repozytoriach" + +#: kallithea/templates/admin/settings/settings_visual.html:83 +msgid "Show private repo icon on repositories" +msgstr "Pokazuj w prywatnym repo ikonę w repozytoriach" + +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:91 +msgid "Meta-Tagging" +msgstr "Tagowanie meta" + +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:110 +msgid "" +"Parses meta tags from repository description field and turns them into " +"colored tags." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 msgid "Add user group" msgstr "Dodaj grupę użytkowników" -#: rhodecode/templates/admin/users_groups/users_group_add.html:10 -#: rhodecode/templates/admin/users_groups/users_groups.html:11 -#: rhodecode/templates/base/base.html:77 rhodecode/templates/base/base.html:94 +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 msgid "User groups" msgstr "Grupy użytkowników" -#: rhodecode/templates/admin/users_groups/users_group_add.html:12 -#: rhodecode/templates/admin/users_groups/users_groups.html:26 -msgid "Add new user group" -msgstr "Dodaj nową grupę użytkowników" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 -msgid "Edit user group" -msgstr "Edytuj grupę użytkowników" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 -msgid "UserGroups" -msgstr "Użytkownicy Grupy" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 -#: rhodecode/templates/admin/users_groups/users_groups.html:38 +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 +#, python-format +msgid "%s user group settings" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "Domyślne uprawnienia" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 msgid "Members" msgstr "Użytkownik" -#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 -msgid "Chosen group members" -msgstr "Wybrane grupy użytkowników" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 -msgid "Remove all elements" -msgstr "Usuń wszystkie elementy" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 -msgid "Available members" -msgstr "Dostępni użytkownicy" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 -msgid "Add all elements" -msgstr "Dodaj wszystkie elementy" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:109 -msgid "No members yet" -msgstr "Nie ma jeszcze żadnego użytkownika" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:117 -msgid "Global Permissions" -msgstr "Uprawnienia globalne" - -#: rhodecode/templates/admin/users_groups/users_groups.html:5 -msgid "User groups administration" -msgstr "Użytkownicy grupy administracji" - -#: rhodecode/templates/admin/users_groups/users_groups.html:55 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 +#, python-format +msgid "User Group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 #, python-format msgid "Confirm to delete this user group: %s" msgstr "Potwierdź usunięcie grupy użytkowników: %s" -#: rhodecode/templates/admin/users_groups/users_groups.html:62 -msgid "There are no user groups yet" -msgstr "Nie ma jeszcze grupy użytkowników" - -#: rhodecode/templates/base/base.html:42 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "Nie ma jeszcze żadnego użytkownika" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "Wybrane grupy użytkowników" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "Usuń wszystkie elementy" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "Dostępni użytkownicy" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "Dodaj wszystkie elementy" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "Użytkownicy grupy administracji" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 +msgid "Add user" +msgstr "Dodaj użytkownika" + +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 +msgid "Users" +msgstr "Użytkownicy" + +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:53 +msgid "Password confirmation" +msgstr "Potwierdzenie hasła" + +#: kallithea/templates/admin/users/user_edit.html:5 +#, python-format +msgid "%s user settings" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "Potwierdź usunięcie tego użytkownika: %s" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 +#, python-format +msgid "" +"This user is in an external Source of Record (%s); some details cannot be" +" managed here." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 +msgid "New password confirmation" +msgstr "Potwierdzenie nowego hasła" + +#: kallithea/templates/admin/users/users.html:5 +msgid "Users administration" +msgstr "Administracja użytkownikami" + +#: kallithea/templates/admin/users/users.html:13 +msgid "users" +msgstr "użytkownicy" + +#: kallithea/templates/admin/users/users.html:54 +msgid "Firstname" +msgstr "imię" + +#: kallithea/templates/admin/users/users.html:55 +msgid "Lastname" +msgstr "nazwisko" + +#: kallithea/templates/admin/users/users.html:56 +msgid "Last login" +msgstr "Ostatnio zalogowany" + +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "" + +#: kallithea/templates/base/base.html:37 #, python-format msgid "Server instance: %s" msgstr "Wystąpienia serwera: %s" -#: rhodecode/templates/base/base.html:52 -msgid "Report a bug" -msgstr "Zgłoś błąd" - -#: rhodecode/templates/base/base.html:121 -#: rhodecode/templates/data_table/_dt_elements.html:9 -#: rhodecode/templates/data_table/_dt_elements.html:11 -#: rhodecode/templates/data_table/_dt_elements.html:13 -#: rhodecode/templates/summary/summary.html:8 +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 msgid "Summary" msgstr "Podsumowanie" -#: rhodecode/templates/base/base.html:122 -#: rhodecode/templates/changelog/changelog.html:15 -#: rhodecode/templates/data_table/_dt_elements.html:17 -#: rhodecode/templates/data_table/_dt_elements.html:19 -#: rhodecode/templates/data_table/_dt_elements.html:21 +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 msgid "Changelog" msgstr "Dziennik zmian" -#: rhodecode/templates/base/base.html:123 -#: rhodecode/templates/data_table/_dt_elements.html:25 -#: rhodecode/templates/data_table/_dt_elements.html:27 -#: rhodecode/templates/data_table/_dt_elements.html:29 -#: rhodecode/templates/files/files.html:12 +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 msgid "Files" msgstr "Pliki" -#: rhodecode/templates/base/base.html:125 +#: kallithea/templates/base/base.html:149 msgid "Switch To" msgstr "Przełącz do" -#: rhodecode/templates/base/base.html:127 -#: rhodecode/templates/base/base.html:279 -msgid "loading..." -msgstr "wczytywanie..." - -#: rhodecode/templates/base/base.html:131 +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 msgid "Options" msgstr "Opcje" -#: rhodecode/templates/base/base.html:137 -#: rhodecode/templates/forks/forks_data.html:21 +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 msgid "Compare fork" msgstr "Porównaj rozwidlenie" -#: rhodecode/templates/base/base.html:139 -#: rhodecode/templates/base/base.html:312 -#: rhodecode/templates/search/search.html:14 -#: rhodecode/templates/search/search.html:54 +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "Porównaj" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 msgid "Search" msgstr "Szukaj" -#: rhodecode/templates/base/base.html:145 +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "Odblokowany" + +#: kallithea/templates/base/base.html:176 msgid "Lock" msgstr "zablokowane" -#: rhodecode/templates/base/base.html:153 +#: kallithea/templates/base/base.html:184 msgid "Follow" msgstr "Obserwuj" -#: rhodecode/templates/base/base.html:154 +#: kallithea/templates/base/base.html:185 msgid "Unfollow" msgstr "Nie obserwuj" -#: rhodecode/templates/base/base.html:157 -#: rhodecode/templates/data_table/_dt_elements.html:33 -#: rhodecode/templates/data_table/_dt_elements.html:35 -#: rhodecode/templates/data_table/_dt_elements.html:37 -#: rhodecode/templates/data_table/_dt_elements.html:74 -#: rhodecode/templates/forks/fork.html:9 +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 msgid "Fork" msgstr "Gałąź" -#: rhodecode/templates/base/base.html:159 +#: kallithea/templates/base/base.html:190 msgid "Create Pull Request" msgstr "Stwórz nowe żądanie połączenia gałęzi" -#: rhodecode/templates/base/base.html:165 -msgid "Show Pull Requests" -msgstr "Nowa prośba o połączenie gałęzi" - -#: rhodecode/templates/base/base.html:165 -msgid "Pull Requests" -msgstr "Połączone gałęzie" - -#: rhodecode/templates/base/base.html:202 +#: kallithea/templates/base/base.html:196 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "Pokaż Prośby Pobrania %s" + +#: kallithea/templates/base/base.html:233 msgid "Not logged in" msgstr "Zaloguj się" -#: rhodecode/templates/base/base.html:209 +#: kallithea/templates/base/base.html:240 msgid "Login to your account" msgstr "Zaloguj się do swojego konta" -#: rhodecode/templates/base/base.html:232 +#: kallithea/templates/base/base.html:263 msgid "Forgot password ?" msgstr "Nie pamiętasz hasła?" -#: rhodecode/templates/base/base.html:255 +#: kallithea/templates/base/base.html:286 msgid "Log Out" msgstr "Wyloguj się" -#: rhodecode/templates/base/base.html:274 -msgid "Switch repository" -msgstr "Przełącz repozytorium" - -#: rhodecode/templates/base/base.html:286 +#: kallithea/templates/base/base.html:311 msgid "Show recent activity" msgstr "Pokaż ostatnią aktywność" -#: rhodecode/templates/base/base.html:287 -#: rhodecode/templates/journal/journal.html:4 +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 msgid "Journal" msgstr "Dziennik" -#: rhodecode/templates/base/base.html:298 +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "Dziennik publiczny" + +#: kallithea/templates/base/base.html:323 msgid "Show public gists" -msgstr "Wyświetl publiczne git" - -#: rhodecode/templates/base/base.html:303 +msgstr "Wyświetl publiczne gists" + +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "Gists" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "Utwórz nowy gist" + +#: kallithea/templates/base/base.html:328 msgid "All public gists" -msgstr "Wszystkie publiczne git" - -#: rhodecode/templates/base/base.html:305 +msgstr "Wszystkie publiczne gists" + +#: kallithea/templates/base/base.html:330 msgid "My public gists" -msgstr "Moje publiczne git" - -#: rhodecode/templates/base/base.html:306 +msgstr "Moje publiczne gists" + +#: kallithea/templates/base/base.html:331 msgid "My private gists" -msgstr "Moje prywatne git" - -#: rhodecode/templates/base/base.html:311 +msgstr "Moje prywatne gists" + +#: kallithea/templates/base/base.html:336 msgid "Search in repositories" msgstr "Szukaj we wszystkich repozytoriach" -#: rhodecode/templates/base/default_perms_box.html:14 -msgid "Inherit default permissions" -msgstr "Dziedziczą uprawnienia domyślne" - -#: rhodecode/templates/base/default_perms_box.html:18 +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:19 #, python-format msgid "" -"Select to inherit permissions from %s settings. With this selected below " -"options does not apply." -msgstr "Wybierz dziedziczone uprawnienia z %s ustawień. Po wybraniu tej opcji poniżej, nie ma ta opcja zastosowania." - -#: rhodecode/templates/base/default_perms_box.html:26 +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:28 msgid "Create repositories" msgstr "Utwórz repozytorium" -#: rhodecode/templates/base/default_perms_box.html:30 +#: kallithea/templates/base/default_perms_box.html:33 msgid "Select this option to allow repository creation for this user" -msgstr "Wybierz tę opcję, aby umożliwić stworzenie repozytorium dla tego użytkownika" - -#: rhodecode/templates/base/default_perms_box.html:35 +msgstr "" +"Wybierz tę opcję, aby umożliwić stworzenie repozytorium dla tego " +"użytkownika" + +#: kallithea/templates/base/default_perms_box.html:40 msgid "Create user groups" msgstr "Tworzenie grup użytkowników" -#: rhodecode/templates/base/default_perms_box.html:39 +#: kallithea/templates/base/default_perms_box.html:45 msgid "Select this option to allow user group creation for this user" -msgstr "Wybierz tę opcję, aby umożliwić utworzenie grupy użytkowników dla tego użytkownika" - -#: rhodecode/templates/base/default_perms_box.html:44 +msgstr "" +"Wybierz tę opcję, aby umożliwić utworzenie grupy użytkowników dla tego " +"użytkownika" + +#: kallithea/templates/base/default_perms_box.html:52 msgid "Fork repositories" msgstr "Rozwidlenie repozytorium" -#: rhodecode/templates/base/default_perms_box.html:48 +#: kallithea/templates/base/default_perms_box.html:57 msgid "Select this option to allow repository forking for this user" -msgstr "Wybierz tę opcję, aby umożliwić rozwidlania repozytorium dla tego użytkownika" - -#: rhodecode/templates/base/perms_summary.html:11 +msgstr "" +"Wybierz tę opcję, aby umożliwić rozwidlania repozytorium dla tego " +"użytkownika" + +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:22 msgid "No permissions defined yet" msgstr "Nie ma jeszcze ustawionych uprawnień" -#: rhodecode/templates/base/perms_summary.html:19 -#: rhodecode/templates/base/perms_summary.html:38 +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 msgid "Permission" msgstr "Uprawnienia" -#: rhodecode/templates/base/perms_summary.html:20 -#: rhodecode/templates/base/perms_summary.html:39 +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 msgid "Edit Permission" msgstr "Edycja Uprawnień" -#: rhodecode/templates/base/root.html:44 +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 msgid "Add another comment" msgstr "Dodaj kolejny komentarz" -#: rhodecode/templates/base/root.html:45 -#: rhodecode/templates/data_table/_dt_elements.html:147 +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 msgid "Stop following this repository" msgstr "Zakończyć obserwację tego repozytorium" -#: rhodecode/templates/base/root.html:46 +#: kallithea/templates/base/root.html:47 msgid "Start following this repository" msgstr "Zacznij obserwację tego repozytorium" -#: rhodecode/templates/base/root.html:47 +#: kallithea/templates/base/root.html:48 msgid "Group" msgstr "Grupa" -#: rhodecode/templates/base/root.html:48 +#: kallithea/templates/base/root.html:49 msgid "members" msgstr "użytkownik" -#: rhodecode/templates/base/root.html:49 -#: rhodecode/templates/pullrequests/pullrequest.html:203 +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 msgid "Loading ..." msgstr "Ładuję..." -#: rhodecode/templates/base/root.html:50 +#: kallithea/templates/base/root.html:51 +msgid "loading ..." +msgstr "ładuję ..." + +#: kallithea/templates/base/root.html:52 msgid "Search truncated" msgstr "Szukaj obcięte" -#: rhodecode/templates/base/root.html:51 +#: kallithea/templates/base/root.html:53 msgid "No matching files" msgstr "Nie ma plików pasujących" -#: rhodecode/templates/base/root.html:52 -#: rhodecode/templates/changelog/changelog.html:45 +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 msgid "Open new pull request" msgstr "Otwórz nową prośbę o połączenie gałęzi" -#: rhodecode/templates/base/root.html:53 +#: kallithea/templates/base/root.html:55 msgid "Open new pull request for selected changesets" msgstr "Otwórz nową prośbę o połączenie gałęzi w zestawieniu zmian" -#: rhodecode/templates/base/root.html:54 +#: kallithea/templates/base/root.html:56 msgid "Show selected changesets __S -> __E" msgstr "Pokaż wybrane zmiany __S -> __E" -#: rhodecode/templates/base/root.html:55 +#: kallithea/templates/base/root.html:57 msgid "Show selected changeset __S" msgstr "Pokaż wybrane zmiany __S -> __E" -#: rhodecode/templates/base/root.html:56 +#: kallithea/templates/base/root.html:58 msgid "Selection link" msgstr "Wybór linku" -#: rhodecode/templates/base/root.html:57 -#: rhodecode/templates/changeset/diff_block.html:8 +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 msgid "Collapse diff" msgstr "Pliki różnic" -#: rhodecode/templates/base/root.html:58 +#: kallithea/templates/base/root.html:60 msgid "Expand diff" msgstr "poprawka różnic" -#: rhodecode/templates/base/root.html:59 +#: kallithea/templates/base/root.html:61 msgid "Failed to revoke permission" msgstr "Nie udało się cofnąć uprawnienia" -#: rhodecode/templates/bookmarks/bookmarks.html:5 +#: kallithea/templates/base/root.html:62 +msgid "confirm to revoke permission for {0}: {1} ?" +msgstr "potwierdzić odwołanie pozwolenie na {0}: {1} ?" + +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:5 #, python-format msgid "%s Bookmarks" msgstr "%s Zakładki" -#: rhodecode/templates/bookmarks/bookmarks.html:26 -msgid "Compare bookmarks" -msgstr "Porównaj zakładki" - -#: rhodecode/templates/bookmarks/bookmarks.html:51 -#: rhodecode/templates/bookmarks/bookmarks_data.html:8 -#: rhodecode/templates/branches/branches.html:50 -#: rhodecode/templates/branches/branches_data.html:8 -#: rhodecode/templates/changelog/changelog_summary_data.html:8 -#: rhodecode/templates/tags/tags.html:51 -#: rhodecode/templates/tags/tags_data.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 msgid "Author" msgstr "Autor" -#: rhodecode/templates/bookmarks/bookmarks.html:52 -#: rhodecode/templates/bookmarks/bookmarks_data.html:9 -#: rhodecode/templates/branches/branches.html:51 -#: rhodecode/templates/branches/branches_data.html:9 -#: rhodecode/templates/changelog/changelog_summary_data.html:5 -#: rhodecode/templates/tags/tags.html:52 -#: rhodecode/templates/tags/tags_data.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 msgid "Revision" msgstr "Rewizja" -#: rhodecode/templates/bookmarks/bookmarks.html:54 -#: rhodecode/templates/bookmarks/bookmarks_data.html:10 -#: rhodecode/templates/branches/branches.html:53 -#: rhodecode/templates/branches/branches_data.html:10 -#: rhodecode/templates/tags/tags.html:54 -#: rhodecode/templates/tags/tags_data.html:10 -msgid "Compare" -msgstr "Porównaj" - -#: rhodecode/templates/branches/branches.html:5 +#: kallithea/templates/branches/branches.html:5 #, python-format msgid "%s Branches" msgstr "%s Gałęzie" -#: rhodecode/templates/branches/branches.html:26 -msgid "Compare branches" -msgstr "porównaj gałęzie" - -#: rhodecode/templates/changelog/changelog.html:6 +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 #, python-format msgid "%s Changelog" msgstr "%s Dziennik zmian" -#: rhodecode/templates/changelog/changelog.html:19 +#: kallithea/templates/changelog/changelog.html:21 #, python-format msgid "showing %d out of %d revision" msgid_plural "showing %d out of %d revisions" -msgstr[0] "pokazano %d z rewizji %d" -msgstr[1] "pokazano %d w rewizjach %d" -msgstr[2] "pokazano %d w rewizjach %d" - -#: rhodecode/templates/changelog/changelog.html:39 +msgstr[0] "pokazano %d z %d rewizji" +msgstr[1] "pokazano %d z %d rewizji" +msgstr[2] "pokazano %d z %d rewizji" + +#: kallithea/templates/changelog/changelog.html:43 msgid "Clear selection" msgstr "Wyczyść zaznaczenie" -#: rhodecode/templates/changelog/changelog.html:42 -#: rhodecode/templates/forks/forks_data.html:19 +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 #, python-format msgid "Compare fork with %s" msgstr "porównaj gałęzie %s" -#: rhodecode/templates/changelog/changelog.html:42 -msgid "Compare fork with parent" -msgstr "porównaj gałąź w rodzicem" - -#: rhodecode/templates/changelog/changelog.html:78 -#: rhodecode/templates/changelog/changelog_summary_data.html:28 -#, python-format -msgid "Click to open associated pull request #%s" -msgstr "Kliknij żeby otworzyć prośbę o połączenie gałęzi #%s" - -#: rhodecode/templates/changelog/changelog.html:102 -#: rhodecode/templates/summary/summary.html:403 -msgid "Show more" -msgstr "Pokaż więcej" - -#: rhodecode/templates/changelog/changelog.html:115 -#: rhodecode/templates/changelog/changelog_summary_data.html:50 -#: rhodecode/templates/changeset/changeset.html:107 -#: rhodecode/templates/changeset/changeset_range.html:86 +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "Wyświetl" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 +#, python-format +msgid "" +"Changeset status: %s\n" +"Click to open associated pull request #%s" +msgstr "Status grupy zmian: %s⏎ Kliknij, aby otworzyć prośby pobrania #%s" + +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 +#, python-format +msgid "Changeset status: %s" +msgstr "Status grupy zmian: %s" + +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:114 +msgid "Changeset has comments" +msgstr "Komentarze Grupy zmian" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 #, python-format msgid "Bookmark %s" msgstr "Zakładki %s" -#: rhodecode/templates/changelog/changelog.html:121 -#: rhodecode/templates/changelog/changelog_summary_data.html:56 -#: rhodecode/templates/changeset/changeset.html:113 -#: rhodecode/templates/changeset/changeset_range.html:92 +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 #, python-format msgid "Tag %s" msgstr "Tagi %s" -#: rhodecode/templates/changelog/changelog.html:126 -#: rhodecode/templates/changelog/changelog_summary_data.html:61 -#: rhodecode/templates/changeset/changeset.html:117 -#: rhodecode/templates/changeset/changeset_range.html:96 +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 #, python-format msgid "Branch %s" msgstr "Gałęzie %s" -#: rhodecode/templates/changelog/changelog.html:286 +#: kallithea/templates/changelog/changelog.html:299 msgid "There are no changes yet" msgstr "Nie ma jeszcze zmian" -#: rhodecode/templates/changelog/changelog_details.html:4 -#: rhodecode/templates/changeset/changeset.html:91 +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 msgid "Removed" msgstr "Usunięto" -#: rhodecode/templates/changelog/changelog_details.html:5 -#: rhodecode/templates/changeset/changeset.html:92 +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 msgid "Changed" msgstr "Zmiana" -#: rhodecode/templates/changelog/changelog_details.html:6 -#: rhodecode/templates/changeset/changeset.html:93 +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 msgid "Added" msgstr "Dodana" -#: rhodecode/templates/changelog/changelog_details.html:8 -#: rhodecode/templates/changelog/changelog_details.html:9 -#: rhodecode/templates/changelog/changelog_details.html:10 -#: rhodecode/templates/changeset/changeset.html:95 -#: rhodecode/templates/changeset/changeset.html:96 -#: rhodecode/templates/changeset/changeset.html:97 +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 #, python-format msgid "Affected %s files" msgstr "Zarażone pliki %s" -#: rhodecode/templates/changelog/changelog_summary_data.html:6 -#: rhodecode/templates/files/files_add.html:75 -#: rhodecode/templates/files/files_edit.html:61 +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 msgid "Commit message" msgstr "Komentarz" -#: rhodecode/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/changelog/changelog_summary_data.html:7 msgid "Age" msgstr "Ostatnia zmiana" -#: rhodecode/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/changelog/changelog_summary_data.html:9 msgid "Refs" msgstr "Gałąź/Etykieta" -#: rhodecode/templates/changelog/changelog_summary_data.html:86 -msgid "Add or upload files directly via RhodeCode" +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" msgstr "Dodaj lub prześlij pliki bezpośrednio przez stronę" -#: rhodecode/templates/changelog/changelog_summary_data.html:89 -#: rhodecode/templates/files/files_add.html:38 -#: rhodecode/templates/files/files_browser.html:31 -msgid "Add new file" -msgstr "Dodaj nowy plik" - -#: rhodecode/templates/changelog/changelog_summary_data.html:95 +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:95 msgid "Push new repo" msgstr "Wyślij zmiany do nowego repo" -#: rhodecode/templates/changelog/changelog_summary_data.html:103 +#: kallithea/templates/changelog/changelog_summary_data.html:103 msgid "Existing repository?" msgstr "Istniejące repozytorium?" -#: rhodecode/templates/changeset/changeset.html:6 +#: kallithea/templates/changeset/changeset.html:6 #, python-format msgid "%s Changeset" msgstr "%s Grupy zmian" -#: rhodecode/templates/changeset/changeset.html:39 -msgid "No parents" -msgstr "Brak rewizji" - -#: rhodecode/templates/changeset/changeset.html:49 -msgid "No children" -msgstr "Brak dzieci" - -#: rhodecode/templates/changeset/changeset.html:62 -#: rhodecode/templates/changeset/changeset_file_comment.html:20 -#: rhodecode/templates/changeset/changeset_range.html:44 +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 msgid "Changeset status" msgstr "Status grupy zmian" -#: rhodecode/templates/changeset/changeset.html:67 -#: rhodecode/templates/changeset/diff_block.html:22 +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 msgid "Raw diff" msgstr "Raw różnic" -#: rhodecode/templates/changeset/changeset.html:68 +#: kallithea/templates/changeset/changeset.html:58 msgid "Patch diff" msgstr "Poprawka różnic" -#: rhodecode/templates/changeset/changeset.html:69 -#: rhodecode/templates/changeset/diff_block.html:23 +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 msgid "Download diff" msgstr "Pobierz różnice" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "%d comment" msgid_plural "%d comments" @@ -3766,8 +4763,8 @@ msgstr[0] "%d komentarz" msgstr[1] "%d komentarzy" msgstr[2] "%d komentarzy" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "(%d inline)" msgid_plural "(%d inline)" @@ -3775,14 +4772,14 @@ msgstr[0] "(%d linii)" msgstr[1] "(%d linii)" msgstr[2] "(%d linii)" -#: rhodecode/templates/changeset/changeset.html:103 -#: rhodecode/templates/changeset/changeset_range.html:82 +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 msgid "merge" msgstr "połącz" -#: rhodecode/templates/changeset/changeset.html:126 -#: rhodecode/templates/compare/compare_diff.html:40 -#: rhodecode/templates/pullrequests/pullrequest_show.html:113 +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 #, python-format msgid "%s file changed" msgid_plural "%s files changed" @@ -3790,9 +4787,9 @@ msgstr[0] "%s plik został zmieniony" msgstr[1] "%s pliki zostały zmienione" msgstr[2] "%s plików zostało zmienionych" -#: rhodecode/templates/changeset/changeset.html:128 -#: rhodecode/templates/compare/compare_diff.html:42 -#: rhodecode/templates/pullrequests/pullrequest_show.html:115 +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 #, python-format msgid "%s file changed with %s insertions and %s deletions" msgid_plural "%s files changed with %s insertions and %s deletions" @@ -3800,137 +4797,171 @@ msgstr[0] "%s plik został zmieniony z %s inercjami i %s usunięciami" msgstr[1] "%s plików zostało zmienionych z %s inercjami i %s usunięciami" msgstr[2] "%s plików zostało zmienionych z %s inercjami i %s usunięciami" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Showing a huge diff might take some time and resources" msgstr "Pokazuje pełną edycję, może zająć to trochę czasu i zasobów" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Show full diff" msgstr "Pokaż pełną historię" -#: rhodecode/templates/changeset/changeset_file_comment.html:30 -#, python-format -msgid "Status change on pull request #%s" -msgstr "Wszystkie prośby połączenia gałęzi %s" - -#: rhodecode/templates/changeset/changeset_file_comment.html:32 +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 +#, python-format +msgid "Vote on pull request #%s" +msgstr "Głosowanie do grupy zmian #%s" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 #, python-format msgid "Comment on pull request #%s" msgstr "Komentarz połączenia gałęzi %s" -#: rhodecode/templates/changeset/changeset_file_comment.html:55 +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Status change on changeset" +msgstr "Zmiana statusu w grupie zmian" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Comment on changeset" +msgstr "Skomentuj grupę zmian" + +#: kallithea/templates/changeset/changeset_file_comment.html:63 msgid "Submitting..." msgstr "Przesyłanie..." -#: rhodecode/templates/changeset/changeset_file_comment.html:58 +#: kallithea/templates/changeset/changeset_file_comment.html:66 msgid "Commenting on line {1}." msgstr "Komentując linię {1}." -#: rhodecode/templates/changeset/changeset_file_comment.html:59 -#: rhodecode/templates/changeset/changeset_file_comment.html:145 +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 #, python-format msgid "Comments parsed using %s syntax with %s support." msgstr "Komentarze analizowane za pomocą %s składni od %s wsparcia." -#: rhodecode/templates/changeset/changeset_file_comment.html:61 -#: rhodecode/templates/changeset/changeset_file_comment.html:147 -msgid "" -"Use @username inside this text to send notification to this RhodeCode user" -msgstr "Użyj @username wewnątrz tego tekstu, aby wysłać powiadomienie do użytkownika strony" - -#: rhodecode/templates/changeset/changeset_file_comment.html:65 -#: rhodecode/templates/changeset/changeset_file_comment.html:152 +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "" +"Użyj @username wewnątrz tego tekstu, aby wysłać powiadomienie do " +"użytkownika strony" + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 msgid "Preview" msgstr "Podgląd" -#: rhodecode/templates/changeset/changeset_file_comment.html:72 -#: rhodecode/templates/changeset/changeset_file_comment.html:170 +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 msgid "Comment preview" msgstr "Podgląd komentarza" -#: rhodecode/templates/changeset/changeset_file_comment.html:80 -#: rhodecode/templates/changeset/changeset_file_comment.html:177 -#: rhodecode/templates/email_templates/changeset_comment.html:16 -#: rhodecode/templates/email_templates/pull_request_comment.html:16 +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 msgid "Comment" msgstr "Komentarz" -#: rhodecode/templates/changeset/changeset_file_comment.html:81 -msgid "Cancel" -msgstr "Anuluj" - -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "You need to be logged in to comment." msgstr "Musisz być zalogowany żeby komentarz." -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "Login now" msgstr "Zaloguj się teraz" -#: rhodecode/templates/changeset/changeset_file_comment.html:92 +#: kallithea/templates/changeset/changeset_file_comment.html:100 msgid "Hide" msgstr "Ukryj" -#: rhodecode/templates/changeset/changeset_file_comment.html:149 -msgid "Change status" -msgstr "Zmień status" - -#: rhodecode/templates/changeset/changeset_file_comment.html:179 -msgid "Comment and close" -msgstr "Skomentuj i zamknij" - -#: rhodecode/templates/changeset/changeset_range.html:5 +#: kallithea/templates/changeset/changeset_file_comment.html:159 +msgid "Vote for pull request status" +msgstr "Zagłosuj na żądanie na grupę zmian" + +#: kallithea/templates/changeset/changeset_file_comment.html:161 +msgid "Change changeset status" +msgstr "Zmiana statusu grupy zmian" + +#: kallithea/templates/changeset/changeset_file_comment.html:179 +msgid "Close (when approved or rejected)" +msgstr "Zamknij (po zatwierdzeniu lub odrzuceniu)" + +#: kallithea/templates/changeset/changeset_range.html:5 #, python-format msgid "%s Changesets" msgstr "%s Zestawienie zmian" -#: rhodecode/templates/changeset/changeset_range.html:52 +#: kallithea/templates/changeset/changeset_range.html:59 msgid "Files affected" msgstr "Pliki naruszone" -#: rhodecode/templates/changeset/diff_block.html:21 +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 msgid "Show full diff for this file" msgstr "Pokaż pełną edycję tego pliku" -#: rhodecode/templates/changeset/diff_block.html:29 +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Show full side-by-side diff for this file" +msgstr "Pokaż pełną listę zmian i różnic obok siebie" + +#: kallithea/templates/changeset/diff_block.html:38 msgid "Show inline comments" msgstr "Pokaż online komentarz" -#: rhodecode/templates/changeset/diff_block.html:53 +#: kallithea/templates/changeset/diff_block.html:62 msgid "Show file at latest version in this repo" msgstr "Pokaż plik w najnowszej wersji, w tym repo" -#: rhodecode/templates/changeset/diff_block.html:54 +#: kallithea/templates/changeset/diff_block.html:64 msgid "Show file at initial version in this repo" msgstr "Pokaż plik w pierwotnej wersji w repo" -#: rhodecode/templates/compare/compare_cs.html:4 +#: kallithea/templates/compare/compare_cs.html:4 msgid "No changesets" msgstr "Brak zestawienia zmian" -#: rhodecode/templates/compare/compare_cs.html:32 +#: kallithea/templates/compare/compare_cs.html:8 msgid "Ancestor" msgstr "Przodek" -#: rhodecode/templates/compare/compare_diff.html:5 +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 #, python-format msgid "%s Compare" msgstr "%s Porównaj" -#: rhodecode/templates/compare/compare_diff.html:9 +#: kallithea/templates/compare/compare_diff.html:16 msgid "Compare revisions" msgstr "Porównaj wersje" -#: rhodecode/templates/compare/compare_diff.html:33 -#: rhodecode/templates/pullrequests/pullrequest_show.html:106 +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 #, python-format msgid "Showing %s commit" msgid_plural "Showing %s commits" @@ -3938,279 +4969,272 @@ msgstr[0] "Pokaż %s komentarz" msgstr[1] "Pokaż %s komentarze" msgstr[2] "Pokaż %s komentarze" -#: rhodecode/templates/compare/compare_diff.html:48 -#: rhodecode/templates/pullrequests/pullrequest_show.html:121 +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 msgid "No files" msgstr "Brak plików" -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -msgid "confirm to show potentially huge diff" -msgstr "potwierdź pokazanie pełnej edycji" - -#: rhodecode/templates/data_table/_dt_elements.html:54 -#: rhodecode/templates/summary/summary.html:69 +#: kallithea/templates/data_table/_dt_elements.html:63 msgid "Mercurial repository" msgstr "Repozytorium mercurial" -#: rhodecode/templates/data_table/_dt_elements.html:56 -#: rhodecode/templates/summary/summary.html:72 +#: kallithea/templates/data_table/_dt_elements.html:65 msgid "Git repository" msgstr "Repozytorium git" -#: rhodecode/templates/data_table/_dt_elements.html:74 -#, python-format -msgid "Fork of %s" -msgstr "Nazwa rozgałęzienia %s" - -#: rhodecode/templates/data_table/_dt_elements.html:88 +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "Publiczne repozytorium" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:96 msgid "No changesets yet" msgstr "Nie ma jeszcze zestawienia zmian" -#: rhodecode/templates/data_table/_dt_elements.html:95 -#: rhodecode/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 #, python-format msgid "Subscribe to %s rss feed" msgstr "Subskrybuj %s kanał rss" -#: rhodecode/templates/data_table/_dt_elements.html:103 -#: rhodecode/templates/data_table/_dt_elements.html:105 +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 #, python-format msgid "Subscribe to %s atom feed" msgstr "Subskrybuj %s kanał atom" -#: rhodecode/templates/data_table/_dt_elements.html:122 -#, python-format -msgid "Confirm to delete this repository: %s" -msgstr "Potwierdź usunięcie repozytorium: %s" - -#: rhodecode/templates/data_table/_dt_elements.html:137 -#, python-format -msgid "Confirm to delete this user: %s" -msgstr "Potwierdź usunięcie tego użytkownika: %s" - -#: rhodecode/templates/email_templates/changeset_comment.html:4 -#: rhodecode/templates/email_templates/pull_request.html:4 -#: rhodecode/templates/email_templates/pull_request_comment.html:4 -msgid "URL" -msgstr "Adres URL" - -#: rhodecode/templates/email_templates/changeset_comment.html:6 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:6 #, python-format msgid "%s commented on a %s changeset." msgstr "%s komentarzy %s zestawów zmian." -#: rhodecode/templates/email_templates/changeset_comment.html:14 +#: kallithea/templates/email_templates/changeset_comment.html:9 msgid "The changeset status was changed to" msgstr "Status zestawienia zmian został zmieniony na" -#: rhodecode/templates/email_templates/main.html:8 -msgid "This is a notification from RhodeCode." +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." msgstr "To jest powiadomienie z strony" -#: rhodecode/templates/email_templates/password_reset.html:4 +#: kallithea/templates/email_templates/password_reset.html:4 #, python-format msgid "Hello %s" msgstr "Witaj %s" -#: rhodecode/templates/email_templates/password_reset.html:5 +#: kallithea/templates/email_templates/password_reset.html:5 msgid "We received a request to create a new password for your account." msgstr "Otrzymaliśmy prośbę o utworzenie nowego hasła do twojego konta." -#: rhodecode/templates/email_templates/password_reset.html:6 +#: kallithea/templates/email_templates/password_reset.html:6 msgid "You can generate it by clicking following URL" msgstr "Możesz wygenerować nowe hasło klikając w link URL poniżej:" -#: rhodecode/templates/email_templates/password_reset.html:10 +#: kallithea/templates/email_templates/password_reset.html:10 msgid "Please ignore this email if you did not request a new password ." msgstr "Proszę zignorować tą wiadomość, jeśli nie poproś o nowe hasło." -#: rhodecode/templates/email_templates/pull_request.html:6 +#: kallithea/templates/email_templates/pull_request.html:6 #, python-format msgid "" -"%s opened a pull request for repository %s and wants you to review changes." -msgstr "%s zgłosił wniosek połączenia w repozytorium %s i chce żeby sprawdzić zmiany." - -#: rhodecode/templates/email_templates/pull_request.html:8 -#: rhodecode/templates/pullrequests/pullrequest.html:34 -#: rhodecode/templates/pullrequests/pullrequest_data.html:14 -#: rhodecode/templates/pullrequests/pullrequest_show.html:25 +"%s opened a pull request for repository %s and wants you to review " +"changes." +msgstr "" +"%s zgłosił wniosek połączenia w repozytorium %s i chce żeby sprawdzić " +"zmiany." + +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 msgid "Title" msgstr "Tytuł" -#: rhodecode/templates/email_templates/pull_request_comment.html:6 +#: kallithea/templates/email_templates/pull_request_comment.html:6 #, python-format msgid "%s commented on pull request \"%s\"" msgstr "%s skomentował nowe połączenie gałęzi \"%s\"" -#: rhodecode/templates/email_templates/pull_request_comment.html:10 +#: kallithea/templates/email_templates/pull_request_comment.html:10 msgid "Pull request was closed with status" msgstr "Wniosek połączenia został zamknięty ze statusem" -#: rhodecode/templates/email_templates/pull_request_comment.html:12 +#: kallithea/templates/email_templates/pull_request_comment.html:12 msgid "Pull request changed status" msgstr "Wniosek połączenia zmienił status" -#: rhodecode/templates/email_templates/registration.html:6 +#: kallithea/templates/email_templates/registration.html:6 msgid "View this user here" msgstr "Zobacz tego użytkownika tutaj" -#: rhodecode/templates/errors/error_document.html:55 +#: kallithea/templates/errors/error_document.html:47 #, python-format msgid "You will be redirected to %s in %s seconds" msgstr "Zostaniesz przekierowany do %s za %s sekund" -#: rhodecode/templates/files/file_diff.html:4 +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "Pliki z listą zmian i różnic: %s" + +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 +msgid "File diff" +msgstr "Pliki różnic" + +#: kallithea/templates/files/diff_2way.html:58 +msgid "ignore white space" +msgstr "ignoruj spacje" + +#: kallithea/templates/files/diff_2way.html:59 +msgid "turn on edit mode" +msgstr "włączyć tryb edycji" + +#: kallithea/templates/files/file_diff.html:4 #, python-format msgid "%s File Diff" msgstr "%s Pliki różnic" -#: rhodecode/templates/files/file_diff.html:8 -msgid "File diff" -msgstr "Pliki różnic" - -#: rhodecode/templates/files/files.html:4 -#: rhodecode/templates/files/files.html:76 +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 #, python-format msgid "%s Files" msgstr "Pliki %s" -#: rhodecode/templates/files/files.html:30 -#: rhodecode/templates/files/files_add.html:31 -#: rhodecode/templates/files/files_edit.html:31 -msgid "Branch" -msgstr "gałąź" - -#: rhodecode/templates/files/files_add.html:4 +#: kallithea/templates/files/files_add.html:4 #, python-format msgid "%s Files Add" msgstr "Pliki %s" -#: rhodecode/templates/files/files_add.html:19 -msgid "Add file" -msgstr "Dodaj plik" - -#: rhodecode/templates/files/files_add.html:43 -msgid "File Name" -msgstr "Nazwa Pliku" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:56 -msgid "or" -msgstr "lub" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:52 -msgid "Upload file" -msgstr "Dodaj plik" - -#: rhodecode/templates/files/files_add.html:56 -msgid "Create new file" -msgstr "Utwórz nowy plik" - -#: rhodecode/templates/files/files_add.html:61 -#: rhodecode/templates/files/files_edit.html:37 -#: rhodecode/templates/files/files_ypjax.html:3 +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" +msgstr "Dodaj nowy plik" + +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 msgid "Location" msgstr "Położenie" -#: rhodecode/templates/files/files_add.html:65 -msgid "use / to separate directories" -msgstr "Użyj / do oddzielenia katalogów" - -#: rhodecode/templates/files/files_add.html:79 -#: rhodecode/templates/files/files_edit.html:65 +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 +msgid "or" +msgstr "lub" + +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:58 +msgid "New file mode" +msgstr "Nowy tryb pliku" + +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 msgid "Commit changes" msgstr "Zatwierdź zmiany" -#: rhodecode/templates/files/files_browser.html:13 -msgid "View" -msgstr "Widok" - -#: rhodecode/templates/files/files_browser.html:14 +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "rewizja" + +#: kallithea/templates/files/files_browser.html:14 msgid "Previous revision" msgstr "poprzednia wersja" -#: rhodecode/templates/files/files_browser.html:16 +#: kallithea/templates/files/files_browser.html:16 msgid "Next revision" msgstr "następna wersja" -#: rhodecode/templates/files/files_browser.html:23 +#: kallithea/templates/files/files_browser.html:22 msgid "Follow current branch" msgstr "Obserwuj aktualną gałąź" -#: rhodecode/templates/files/files_browser.html:27 -msgid "Search file list" -msgstr "Lista szukanych plików" - -#: rhodecode/templates/files/files_browser.html:35 +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:29 msgid "Loading file list..." msgstr "Wczytywanie listy plików..." -#: rhodecode/templates/files/files_browser.html:48 +#: kallithea/templates/files/files_browser.html:42 msgid "Size" msgstr "Rozmiar" -#: rhodecode/templates/files/files_browser.html:49 +#: kallithea/templates/files/files_browser.html:43 msgid "Mimetype" msgstr "Typ MIME" -#: rhodecode/templates/files/files_browser.html:50 +#: kallithea/templates/files/files_browser.html:44 msgid "Last Revision" msgstr "Rewizja" -#: rhodecode/templates/files/files_browser.html:51 +#: kallithea/templates/files/files_browser.html:45 msgid "Last modified" msgstr "Ostatnio modyfikowany" -#: rhodecode/templates/files/files_browser.html:52 +#: kallithea/templates/files/files_browser.html:46 msgid "Last committer" msgstr "Autor" -#: rhodecode/templates/files/files_edit.html:4 -#, python-format -msgid "%s Files Edit" -msgstr "Pliki %s" - -#: rhodecode/templates/files/files_edit.html:19 +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "%s Usuń Plik" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "Usuń plik" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:25 msgid "Edit file" msgstr "Edytuj plik" -#: rhodecode/templates/files/files_edit.html:47 -#: rhodecode/templates/files/files_source.html:23 -msgid "Show annotation" -msgstr "pokaż adnotacje" - -#: rhodecode/templates/files/files_edit.html:49 -#: rhodecode/templates/files/files_source.html:26 -msgid "Download as raw" -msgstr "Pobierz jako raw" - -#: rhodecode/templates/files/files_edit.html:52 +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:58 msgid "Source" msgstr "Źródło" -#: rhodecode/templates/files/files_edit.html:57 +#: kallithea/templates/files/files_edit.html:63 msgid "Editing file" msgstr "Edycja pliku" -#: rhodecode/templates/files/files_history_box.html:2 -msgid "History" -msgstr "Historia" - -#: rhodecode/templates/files/files_history_box.html:9 -msgid "Diff to revision" -msgstr "Różnice do rewizji" - -#: rhodecode/templates/files/files_history_box.html:10 -msgid "Show at revision" -msgstr "Wskaż zmiany" - -#: rhodecode/templates/files/files_history_box.html:11 -msgid "Show full history" -msgstr "Pokaż pełną historię" - -#: rhodecode/templates/files/files_history_box.html:16 +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 #, python-format msgid "%s author" msgid_plural "%s authors" @@ -4218,219 +5242,225 @@ msgstr[0] "%s autor" msgstr[1] "%s autorzy" msgstr[2] "%s autorzy" -#: rhodecode/templates/files/files_source.html:6 -msgid "Load file history" -msgstr "Załaduj historię pliku" - -#: rhodecode/templates/files/files_source.html:21 -msgid "Show source" +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:8 +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:11 +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" msgstr "Pokaż źródło" -#: rhodecode/templates/files/files_source.html:29 -#, python-format -msgid "Edit on branch:%s" -msgstr "Usunięta gałąź: %s" - -#: rhodecode/templates/files/files_source.html:31 -msgid "Edit on branch:?" -msgstr "Usunięta gałąź: %s" - -#: rhodecode/templates/files/files_source.html:31 +#: kallithea/templates/files/files_source.html:38 +#, python-format +msgid "Edit on Branch:%s" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "Edycja plików binarnych jest zabroniona" + +#: kallithea/templates/files/files_source.html:44 msgid "Editing files allowed only when on branch head revision" -msgstr "Edycja plików dozwolona tylko wtedy, gdy rewizja jest w trakcie rewizji głównej gałęzi" - -#: rhodecode/templates/files/files_source.html:46 +msgstr "" +"Edycja plików dozwolona tylko wtedy, gdy rewizja jest w trakcie rewizji " +"głównej gałęzi" + +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:61 #, python-format msgid "Binary file (%s)" msgstr "Plik binarny (%s)" -#: rhodecode/templates/files/files_source.html:55 +#: kallithea/templates/files/files_source.html:71 msgid "File is too big to display" msgstr "Plik jest za duży do wyświetlenia" -#: rhodecode/templates/files/files_ypjax.html:5 +#: kallithea/templates/files/files_ypjax.html:5 msgid "annotation" msgstr "adnotacja" -#: rhodecode/templates/files/files_ypjax.html:15 -msgid "Go back" -msgstr "Idź wstecz" - -#: rhodecode/templates/files/files_ypjax.html:16 +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "Wróć" + +#: kallithea/templates/files/files_ypjax.html:24 msgid "No files at given path" msgstr "Brak plików w danej ścieżce" -#: rhodecode/templates/followers/followers.html:5 +#: kallithea/templates/followers/followers.html:5 #, python-format msgid "%s Followers" msgstr "Obserwatorzy %s" -#: rhodecode/templates/followers/followers.html:9 -#: rhodecode/templates/summary/summary.html:183 -#: rhodecode/templates/summary/summary.html:184 +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 msgid "Followers" msgstr "Obserwuje" -#: rhodecode/templates/followers/followers_data.html:12 +#: kallithea/templates/followers/followers_data.html:12 msgid "Started following -" msgstr "Rozpoczęto obserwację -" -#: rhodecode/templates/forks/fork.html:5 -#, python-format -msgid "%s Fork" -msgstr "Gałęzi %s" - -#: rhodecode/templates/forks/fork.html:28 +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:30 msgid "Fork name" msgstr "Nazwa rozgałęzienia" -#: rhodecode/templates/forks/fork.html:65 +#: kallithea/templates/forks/fork.html:71 msgid "Private" msgstr "Prywatny" -#: rhodecode/templates/forks/fork.html:74 +#: kallithea/templates/forks/fork.html:80 msgid "Copy permissions" msgstr "Skopiuj uprawnienia" -#: rhodecode/templates/forks/fork.html:78 +#: kallithea/templates/forks/fork.html:84 msgid "Copy permissions from forked repository" msgstr "Skopiuj zezwolenia z rozwidlenia repozytorium" -#: rhodecode/templates/forks/fork.html:84 +#: kallithea/templates/forks/fork.html:90 msgid "Update after clone" msgstr "Aktualizuj po klonowaniu" -#: rhodecode/templates/forks/fork.html:88 +#: kallithea/templates/forks/fork.html:94 msgid "Checkout source after making a clone" msgstr "Sprawdź źródło po wykonaniu klonowania" -#: rhodecode/templates/forks/fork.html:93 -msgid "Fork this repository" -msgstr "Gałąź tego repozytorium" - -#: rhodecode/templates/forks/forks.html:5 +#: kallithea/templates/forks/fork.html:99 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 #, python-format msgid "%s Forks" -msgstr "Gałęzi %s" - -#: rhodecode/templates/forks/forks.html:9 -#: rhodecode/templates/summary/summary.html:189 -#: rhodecode/templates/summary/summary.html:190 +msgstr "Gałąź %s" + +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 msgid "Forks" msgstr "Gałęzie" -#: rhodecode/templates/forks/forks_data.html:17 +#: kallithea/templates/forks/forks_data.html:17 msgid "Forked" msgstr "Rozgałęziony" -#: rhodecode/templates/forks/forks_data.html:42 +#: kallithea/templates/forks/forks_data.html:42 msgid "There are no forks yet" msgstr "Nie ma jeszcze gałęzi" -#: rhodecode/templates/journal/journal.html:21 +#: kallithea/templates/journal/journal.html:24 msgid "ATOM journal feed" msgstr "Dziennik kanału ATOM" -#: rhodecode/templates/journal/journal.html:22 +#: kallithea/templates/journal/journal.html:25 msgid "RSS journal feed" msgstr "Dziennik kanału RSS" -#: rhodecode/templates/journal/journal.html:32 -msgid "Refresh" -msgstr "Odśwież" - -#: rhodecode/templates/journal/journal.html:35 -#: rhodecode/templates/journal/public_journal.html:24 -msgid "ATOM feed" -msgstr "Kanał ATOM" - -#: rhodecode/templates/journal/journal.html:51 -msgid "Watched" -msgstr "Obserwowane" - -#: rhodecode/templates/journal/journal_data.html:55 +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "Moje repo" + +#: kallithea/templates/journal/journal_data.html:55 msgid "No entries yet" msgstr "Brak wpisów jeszcze" -#: rhodecode/templates/journal/public_journal.html:4 -#: rhodecode/templates/journal/public_journal.html:21 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 msgid "Public Journal" msgstr "Dziennik Publiczny" -#: rhodecode/templates/journal/public_journal.html:13 +#: kallithea/templates/journal/public_journal.html:16 msgid "ATOM public journal feed" msgstr "Publiczny dziennik kanału ATOM" -#: rhodecode/templates/journal/public_journal.html:14 +#: kallithea/templates/journal/public_journal.html:17 msgid "RSS public journal feed" msgstr "Publiczny dziennik kanału RSS" -#: rhodecode/templates/pullrequests/pullrequest.html:4 -#: rhodecode/templates/pullrequests/pullrequest.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 msgid "New pull request" msgstr "Nowa prośba o połączenie gałęzi" -#: rhodecode/templates/pullrequests/pullrequest.html:25 -msgid "Create new pull request" -msgstr "Stwórz nowe żądanie połączenia gałęzi" - -#: rhodecode/templates/pullrequests/pullrequest.html:47 +#: kallithea/templates/pullrequests/pullrequest.html:44 msgid "Write a short description on this pull request" msgstr "Napisz krótki opis tego tego połączenia gałęzi" -#: rhodecode/templates/pullrequests/pullrequest.html:53 +#: kallithea/templates/pullrequests/pullrequest.html:50 msgid "Changeset flow" msgstr "Przepływ zestawienia zmian" -#: rhodecode/templates/pullrequests/pullrequest.html:60 -#: rhodecode/templates/pullrequests/pullrequest_show.html:65 +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 msgid "Origin repository" msgstr "Repozytorium git" -#: rhodecode/templates/pullrequests/pullrequest.html:85 -msgid "Send pull request" -msgstr "Wyślij prośbę o połączenie gałęzi" - -#: rhodecode/templates/pullrequests/pullrequest.html:94 -#: rhodecode/templates/pullrequests/pullrequest_show.html:137 +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 msgid "Pull request reviewers" msgstr "Recenzje wniosków połączenia gałęzi" -#: rhodecode/templates/pullrequests/pullrequest.html:103 -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 msgid "owner" msgstr "właściciel" -#: rhodecode/templates/pullrequests/pullrequest.html:115 +#: kallithea/templates/pullrequests/pullrequest.html:114 msgid "Add reviewer to this pull request." msgstr "Pokarz wszystkie zmiany" -#: rhodecode/templates/pullrequests/pullrequest.html:129 +#: kallithea/templates/pullrequests/pullrequest.html:128 msgid "Detailed compare view" msgstr "Szczegółowe porównanie widoku" -#: rhodecode/templates/pullrequests/pullrequest.html:150 +#: kallithea/templates/pullrequests/pullrequest.html:149 msgid "Destination repository" msgstr "Repozytorium docelowe" -#: rhodecode/templates/pullrequests/pullrequest_show.html:4 +#: kallithea/templates/pullrequests/pullrequest_show.html:4 #, python-format msgid "%s Pull Request #%s" msgstr "%s Połączonych gałęzi #%s" -#: rhodecode/templates/pullrequests/pullrequest_show.html:35 +#: kallithea/templates/pullrequests/pullrequest_show.html:36 msgid "Review status" msgstr "Nowy status" -#: rhodecode/templates/pullrequests/pullrequest_show.html:40 -msgid "Pull request status" -msgstr "Żądanie statusu połączenia gałęzi" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 +msgid "Pull request status calculated from votes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:56 msgid "Still not reviewed by" msgstr "Nie ma jeszcze recenzenta" -#: rhodecode/templates/pullrequests/pullrequest_show.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:60 #, python-format msgid "%d reviewer" msgid_plural "%d reviewers" @@ -4438,241 +5468,256 @@ msgstr[0] "%d recenzent" msgstr[1] "%d recenzenci" msgstr[2] "%d recenzentów" -#: rhodecode/templates/pullrequests/pullrequest_show.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:62 msgid "Pull request was reviewed by all reviewers" msgstr "Połączenie gałęzi zostało zweryfikowane przez wszystkich recenzentów" -#: rhodecode/templates/pullrequests/pullrequest_show.html:89 -msgid "Created on" -msgstr "Utworzono" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:102 +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 +msgid "Pull changes" +msgstr "Pobierz zmiany" + +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "reviewer" +msgstr "recenzent" + +#: kallithea/templates/pullrequests/pullrequest_show.html:133 +msgid "Add or remove reviewer to this pull request." +msgstr "Pokarz wszystkie zmiany" + +#: kallithea/templates/pullrequests/pullrequest_show.html:137 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 msgid "Compare view" msgstr "Wyświetl porównanie" -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 -msgid "reviewer" -msgstr "recenzent" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:164 -msgid "Add or remove reviewer to this pull request." -msgstr "Pokarz wszystkie zmiany" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:168 -msgid "Save changes" -msgstr "Bez zmian" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:4 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 #, python-format msgid "%s Pull Requests" msgstr "%s Moje prośby połączenia gałęzi" -#: rhodecode/templates/search/search.html:6 -msgid "Search repository" -msgstr "Szukaj w repozytorium: %s" - -#: rhodecode/templates/search/search.html:8 -#: rhodecode/templates/search/search.html:16 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 +#, python-format +msgid "Pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 +#, python-format +msgid "Pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 +msgid "Hide closed pull requests" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 +msgid "Show closed pull requests too" +msgstr "" + +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 msgid "Search in all repositories" msgstr "Szukaj we wszystkich repozytoriach" -#: rhodecode/templates/search/search.html:50 +#: kallithea/templates/search/search.html:53 msgid "Search term" msgstr "Szukana fraza" -#: rhodecode/templates/search/search.html:62 +#: kallithea/templates/search/search.html:65 msgid "Search in" msgstr "Szukaj w" -#: rhodecode/templates/search/search.html:65 +#: kallithea/templates/search/search.html:68 msgid "File contents" msgstr "Zawartość pliku" -#: rhodecode/templates/search/search.html:66 +#: kallithea/templates/search/search.html:69 msgid "Commit messages" msgstr "Komunikaty" -#: rhodecode/templates/search/search.html:67 +#: kallithea/templates/search/search.html:70 msgid "File names" msgstr "Nazwy plików" -#: rhodecode/templates/search/search_commit.html:35 -#: rhodecode/templates/search/search_content.html:21 -#: rhodecode/templates/search/search_path.html:15 +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 msgid "Permission denied" msgstr "Brak uprawnień" -#: rhodecode/templates/summary/summary.html:4 +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "%s Statystyki" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 +#, python-format +msgid "%s ATOM feed" +msgstr "%s ATOM" + +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 +#, python-format +msgid "%s RSS feed" +msgstr "%s RSS" + +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "Włącz" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "Statystyki zebrane: " + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "pliki" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "Pokaż więcej" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "komunikaty" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "pliki dodane" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "pliki zmienione" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "pliki usunięte" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "komunikaty" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "plik dodany" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "plik zmieniony" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "plik usunięty" + +#: kallithea/templates/summary/summary.html:4 #, python-format msgid "%s Summary" msgstr "Podsumowanie %s" -#: rhodecode/templates/summary/summary.html:16 -#, python-format -msgid "%s ATOM feed" -msgstr "%s ATOM" - -#: rhodecode/templates/summary/summary.html:17 -#, python-format -msgid "%s RSS feed" -msgstr "%s RSS" - -#: rhodecode/templates/summary/summary.html:62 +#: kallithea/templates/summary/summary.html:16 #, python-format msgid "Repository locked by %s" msgstr "Repozytorium zablokowane przez %s" -#: rhodecode/templates/summary/summary.html:64 +#: kallithea/templates/summary/summary.html:18 msgid "Repository unlocked" msgstr "Repozytorium odblokowane" -#: rhodecode/templates/summary/summary.html:83 -#, python-format -msgid "Non changable ID %s" -msgstr "Brak ID pełnej zmiany %s" - -#: rhodecode/templates/summary/summary.html:88 -msgid "Public" -msgstr "Publiczny" - -#: rhodecode/templates/summary/summary.html:88 -#: rhodecode/templates/summary/summary.html:89 -msgid "Fork of" -msgstr "Gałąź z" - -#: rhodecode/templates/summary/summary.html:97 -msgid "Remote clone" -msgstr "zdalne klonowanie" - -#: rhodecode/templates/summary/summary.html:117 -msgid "Contact" -msgstr "Kontakt" - -#: rhodecode/templates/summary/summary.html:131 +#: kallithea/templates/summary/summary.html:76 msgid "Clone url" msgstr "Url klonowania" -#: rhodecode/templates/summary/summary.html:136 +#: kallithea/templates/summary/summary.html:81 msgid "Show by Name" msgstr "Pokaż nazwę" -#: rhodecode/templates/summary/summary.html:137 +#: kallithea/templates/summary/summary.html:82 msgid "Show by ID" msgstr "Pokaż ID" -#: rhodecode/templates/summary/summary.html:143 +#: kallithea/templates/summary/summary.html:99 msgid "Trending files" msgstr "Statystyki" -#: rhodecode/templates/summary/summary.html:151 -#: rhodecode/templates/summary/summary.html:167 -msgid "Enable" -msgstr "Włącz" - -#: rhodecode/templates/summary/summary.html:159 +#: kallithea/templates/summary/summary.html:115 msgid "Download" msgstr "Pobierz" -#: rhodecode/templates/summary/summary.html:163 +#: kallithea/templates/summary/summary.html:119 msgid "There are no downloads yet" msgstr "Nie pobrano jeszcze plików" -#: rhodecode/templates/summary/summary.html:165 +#: kallithea/templates/summary/summary.html:121 msgid "Downloads are disabled for this repository" msgstr "Pliki do pobrania są zostały wyłączone dla tego repozytorium" -#: rhodecode/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:127 msgid "Download as zip" msgstr "Pobierz jako zip" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "Check this to download archive with subrepos" msgstr "Zaznacz tu żeby pobrać archiwum z subrepozytorium" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "with subrepos" msgstr "z subrepozytorium" -#: rhodecode/templates/summary/summary.html:197 +#: kallithea/templates/summary/summary.html:163 msgid "Repository Size" msgstr "Rozmiar Repozytorium" -#: rhodecode/templates/summary/summary.html:204 -#: rhodecode/templates/summary/summary.html:206 +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 msgid "Feed" msgstr "Kanał RSS" -#: rhodecode/templates/summary/summary.html:224 -msgid "Commit activity by day / author" -msgstr "komunikaty aktywne w ciągu dnia / autor" - -#: rhodecode/templates/summary/summary.html:232 -msgid "enable" -msgstr "włącz" - -#: rhodecode/templates/summary/summary.html:235 -msgid "Stats gathered: " -msgstr "Statystyki zebrane: " - -#: rhodecode/templates/summary/summary.html:256 +#: kallithea/templates/summary/summary.html:193 msgid "Latest changes" msgstr "Ostatnia aktywność" -#: rhodecode/templates/summary/summary.html:258 +#: kallithea/templates/summary/summary.html:195 msgid "Quick start" msgstr "Szybki start" -#: rhodecode/templates/summary/summary.html:272 -#, python-format -msgid "Readme file from revision %s" -msgstr "Plik Readme z wersji %s" - -#: rhodecode/templates/summary/summary.html:332 +#: kallithea/templates/summary/summary.html:209 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:299 #, python-format msgid "Download %s as %s" msgstr "Pobierz %s jak %s" -#: rhodecode/templates/summary/summary.html:379 -msgid "files" -msgstr "pliki" - -#: rhodecode/templates/summary/summary.html:689 -msgid "commits" -msgstr "komunikaty" - -#: rhodecode/templates/summary/summary.html:690 -msgid "files added" -msgstr "pliki dodane" - -#: rhodecode/templates/summary/summary.html:691 -msgid "files changed" -msgstr "pliki zmienione" - -#: rhodecode/templates/summary/summary.html:692 -msgid "files removed" -msgstr "pliki usunięte" - -#: rhodecode/templates/summary/summary.html:694 -msgid "commit" -msgstr "komunikaty" - -#: rhodecode/templates/summary/summary.html:695 -msgid "file added" -msgstr "plik dodany" - -#: rhodecode/templates/summary/summary.html:696 -msgid "file changed" -msgstr "plik zmieniony" - -#: rhodecode/templates/summary/summary.html:697 -msgid "file removed" -msgstr "plik usunięty" - -#: rhodecode/templates/tags/tags.html:5 +#: kallithea/templates/tags/tags.html:5 #, python-format msgid "%s Tags" msgstr "Etykiety pliku %s" -#: rhodecode/templates/tags/tags.html:26 +#: kallithea/templates/tags/tags.html:29 msgid "Compare tags" msgstr "Porównaj tagi" + diff --git a/rhodecode/i18n/pt_BR/LC_MESSAGES/rhodecode.mo b/kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.mo rename from rhodecode/i18n/pt_BR/LC_MESSAGES/rhodecode.mo rename to kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.mo index 05cee56fb5e23bdb2d4790de56f51a93d636b661..c303d1533666b3f805607194f22df3ae99144005 GIT binary patch literal 82393 zc%1CL2bdhi(Ko)bi840P#^gaDB!TWEk&!?`C~=^0=uRRCA?9}H?pE5}Id*pMbO?dT zIejK46GR3RM6wAs9N2&n7%BKnn?i1y1AZbaeX69Ke-i3jVfR#OPYPF~@Ei*F*&XBk zr-rLEpud|?xGsgm8!(>THGVG&SLFF>K)>1>P_N&Badc_^!zo;o;oX3Fxkfq*6bmaNj)u&)Itbp7}k12M6zgaUZ`2>c2?iuiOLux@`}P`;U8|KQCzc z*Y*IOy-(qmJYRdF-0pj#zP=ew` z22(NKTPWO@!UrfE!t*ta+N7|7!cmO()3E-on}%^eOW`02f7nQCj>4@PQO>1s7=ch_E6x9{$S`iD(N`rgw~&oR?6{;Q{> z-#1UkID0gFnZorc{7Uovyb0wtZ2~@xZvuR$HUa*#n}C<4Cg9CU6b@#1HKCrnngHi# znlQi1ny~J^ZbJM0o6*h&&4}N;8SM-K~hfX}rvfR_(yxff@k zUvJC+9=@;NtIkCEwPylO17>19>@*YYOqmII96;e{3Ihrocs^zVeqYW6-5Izy(GZ5m z-dHzB?T!B3v^U26(B4>|f8Sf_v3{?;58%JqKFB|MAM|e~g;aIQ-v{;oVITDOaSdPC z2lVUpeE_$W_eFg_p^%nrYU6!%ee8>M)k$Fo_iJCk*Fn zo@P=woWeQ#0ZylB_$v*6t>y0C5A`nD4|w#{et_Sb`u*8{=uiJyXm{ONn5Ut$klrv0 z>tfa{LE>W*PtY2R``Li+YqQbM6%RoD0}cRQ?s@>mS3Cgg_s9bPhif&w^8nz{ zpAG>2zog$E9Dwz+(j4SlYYyTE%t5~G=Kzikb1?6F%>f?oKL_m>=Kv0;Y5D6kyi4;v zG6(bas@D6?9Q5;>Ie_OH2LgXKIuPXs9fsQ;)Ils~Nn<*#f(dv~+|pB~V1&uIF4E$HXhEx_-U)A-&bjr@btXm6y3 zd!(^$_Df?QXiuYmzof96!Yk5%my-cJ2WC)iSO)Em(fAn|)ITSK@gI}{-ky>{e{Z00 z2cEwS_Q8)bX!mnXU&RAlf9hcz8|rtRhk4jmDtz)z|Qs?SS{~?O2zuwqt$$D2sh{n=JY@hr(?rJUNT>do_NU zhU?Bn`h>Y?r+Y5w$PIHbKljfC9z8!7<9}l=#{KuXfcxt6z_)HV5BayB2e?k2hk0+G zhk44+!#ppT2YPb!JgnP`=K=25&cnPuJ`eDJhQd?0JXzz55zmmdV zQ+QJja6d2)_!jf%$MJcL|CBuP-`@IG930k<@Wo-#-c%@5cqSw}P+p=%b!(e2jAx zg`fO@=$wyoyB7hssYSr2q~T#j%*zQy)OU6f^K(%V{k)@ye%-6_f6(uji-61PMeP@b z$8x`l80W$Oa5^PG{TBzwcYOf3Ee?Rkf1vPe3SXmepMEsoC8YnQjB&hKMm=9?xOyk> zcvA{@W%zXhUMF{Ae3y2D4n3&fFLwgJR_a1O26O>V!@7`fhc1+#)`j{rUD)S4yTA|M zOW{}wALv5AR-TV>tUn*)bmn6oN6ZI2cbN~k>^>j!H+??l>p)HSHU8lFfbVgde!6~N zJRjq}TI>DYeDv>6TK;9t_s)FqO&`t2d~DMVI|?Z)`qyD|Q9H}HL- zhG%r6-`94d{ad>Mzdun(TWji{6po>=@nH1-w1aiuIT-oxJQ(#pelYs`oQ8it814RW z0s6hh0?>{1G@P~o<2rf)+COap;CkKy-S;*9&IN$eA2j_bO@Bk{{bT{)@XZ47c`F=( zeRQKkkUr)Rz;pLQ0GH-N(C^kmFrGsWL47Ca_j!k)y{isE|8GA8_<#Q)X#Yhm{}0W- z;zG2u_Cl1~a3Sd4Rupc`c)Aedn70u7f9FD!J7FREbB?B8vk-W8tJd@2LiGC?t^c)! zn6Gyiq8~pz6y?`B6#2I}6#d-pQ1oxwp`b^e=KIB=DF1)-`|3jhw>uBTIDdaA`n80@ z?J0cWP|WLEhoQao4@3G^6q2Zy+KIwO#^b}VZ#{Py+WpsI*e_Q91?t^}!ksDHgTieo zJoXou|GR#H`ak#u`t$iOFwWHu$GZLL;aG1Y4u>4N!{JCj>2Qqq%)`;%qQe2#-%>b| z!bcCsI9ELaaCMH*e(U#6N1(m&M*zMvj{uxnjzIkjj{yE2a|Gzb`A1-%U99<*9s&CE z*%4S@I~@r+vFnleKH^A>>-Zzl&guGnnTFRM3Aiji67%)@Bf$?oPa%n(scnt|9vpKN z%Ac#>*B*uP_Z)?O|KTXq^TbiW`}s_ z<b`O;>b>|_%+qbh0+0W6 zEb#Ep`u)D<|M*zo+sem*FWlugjJtds>N(;#!1bKtlnx(<_OCt;{rT;2nAblX2mD!b z9LDqPalnUnwfxG*qra;k4|!A5B=mPag}ZaRC!wD&QaFj%?MdJxcRLw)S~wZ$ho21iTzE3z zdB@4<_d^>0=ET%il+c?k2(eTcKIp5^Se$#Kc6}UaDML;@U`ol zigE37D&RW(RFpgDRE*=eQ_;=^r=tAhnr|6}v{j{6ISu)aJPr7H_GzF$m!F3IU#sbN zorZPwXU+HaX~3J$D4a-PztfcuI9>Sw{XXz?;M3gGfe)P;9;x|GI~{m?k;Y%9@i$U< z5b<;OoDMu3eg^up!x`Gn8Gz^XGcex#87j|dzSA_kN^ zCf4CYXQCg^o{4!_dM4oYk25jumCwRFZ+aHsvF%ylmv%o3dZoz}5^IuLa2DY5(OD?} z)mhMc{Pb+pKk;nf-JWM-ytB?md+ldq90#9`_D(+=1(3#uy`vnc(JR9Tt@NBGy z70yw4;~bSY&H-L+e-7wX^EtqmL(fsY?K!~1+cf>jb5xIW4&b}ix#-u1=K|mA^?Sy- z;FH?U1${aBT+BnyxxmvG&qY0-o{ROp+Id(PL(juFc0UjO&Yg#Kx$r#fyO&Zpfx_p` z16|qVe1wC}2R;nbaF_D||2@wKJm;Jb{K%Y-dgp1mL(WJ0M``{==L4_rIA84y=VSdo zq~$)=d@Egm@vMJ=>I*KwdfD>=z;o^e=*Mvv0M2J!fN|e=0pR(NhHqQ|`t!pJk#FFI z=+Br7G444RBK@cfQU4VeqW%Xi1irj>A;z)JMF=;%2;<%SBFxW_i+~5)Tm(EEa}nS$ zPV?rTY@h`^}dCzm{Es`q#J=^52k4 z0f*Br#rnFJ!W()0Qn)vTms|#Z>tB~){DT%@ez#f#{2s9g{n&L8*6rRJKX(z})4d4r zK6DYvU$6*py?7D$ylWN#9{*Z|b+z8*Sl3%z4*VW=Iq+rt<$(J>m#cn8^Btt=2VahP zI^}ZoYNK0G^#!0AEhh?`y9>{r6sh zd0cV@=HusAqWm^jqW)?6ox2j{kGoRoz?CR}+m+CB+;=75{>hbCCxfm6ec1Xc(6jxo zLjOuvq5sES1vp=*>9<^k`X0Fo{do2&;LnFw0WLqj8sX2b#=LKGHSl8M)!2XMQFuJV z>uSvB&#yr{8()L(ZLYz5?Q{+1Zx;#=qHxwV=+}~KFdwg6gK@ug4e)BkYq5?tz7~A! z78H_*n`*lj^}Td0>U-^4wA1f8;N8mCfe+vQI^f%h*J1zo&2`{UKD`e1mu;>`JDu0# z`&0_YQ~1R7pfl_K8s)}mc=)dY@8A6z^ZVhi!KZC@1N8p0ZU9`4y8-;=^*5mYXK%o| z`R5Iw!-H=`xv4i|UXQsEczF4Zpf9&mIGMudDBO$3eG~9}{!N&dBW?noUvLxZyXz** z_p3Jn?yKDlIBt3~@MZMPh@WyZ;N7C%oj0SuCu;nS`hEY+!0TlietI+dx#D7kn=eNB zaf?y^KKk9Z81rz*V$9DGi-C{FELQnqG4Sj%{k}od@6~dTECwDtu^99I++wWbR~BPF z{;u)s--2=jZozlmEog7MTd+^>bPMWfxJB(yw*XJ~y#;jS5G{B3Ex?cC_4{@Wf2Z~T z@fMX^G<@k6^z+?YFpdvy0ersJaJ5^}?)tZ)o=tB>xgocLer$g$=*gU0QBP6R=iiET zb@Z)(%XPP6f4fJ&AJh6?(eGuqVq9O`s(i$4=+El6A>RhKq5jQo16+pOhH`ZpKjt=+ zpKu%SYU*vk>wRuRe@?m$a60!k)PE6$#MY&**7DbBdpGO%J-1<8_ur;^&f8S)q4j)n z8{qPVhCjF+?W}q``t`HhQP1Gp(XV<9ceow>+x2#o+v9fBx7Y393ukKiU*3-W>2l5g zqQ<{xBy?;xC{u;UK&|HC`b&u{KP`>X#3{r~B2bl?6B=5@$#kiG+jFZCl@ z@Eg>-(VbZ5gYN_$HQfn0;P5*^A1=KU^yrB@v99{vh5dVryReQ5ccHzL@4|dva2M9m z_4<9^U7*iT-UWL7j^_Wt-GJYk8g8uNR(At#JL>mX4X56Xam>0KD))eHtalH->+V6h(f5EZ?{N?4Q2RZYm!t1N z`BOFDh4%nouh#UN?!ox()OsJj2k?AR!*4X+`5pSd?e75hJt+(*?EW3)LxU z-rwH~Jb6*e|LtD*YrLcJ3+_WZhu;Tyo_HVNe*S%`$GZ>p-F_eHe?;S-x({&t+kNP7 zzaGSI)PwO1?ZN&(t_S-{N#n2U0o;0euuuH02lLtge$2abKkD7)e&BQC{n%G#-H&n$ z?#H+;xF7ZX_I`~2@%vSebHCbm??-?8KY;$P{eZ4#4eK9J`_luUbK@R>AI97VFhBQG zNTeZk${$jxyLmqTi28r{Ao6YaAm+LALD11f4`RPw@*vjL8V{*o)I-<@TOI;EIO!pb z`+KXVj)@{?nkh2ec82J}JjC$UE82Q%w6Xc~ye**up@K3N~-18^E`wjhG z_YuHv%p+<)d<1aaPs6T9z*n8|2;g+XBiN7bctq{_j{rWeKLR*^^a$4dkCrGMUxIdq zEI~bcEdiW!8Xmp`czf0o%ch=ehmHm{bQK_KRpJ1=x>iwm*PqulU610SYneCMA5w-f#hI(sRFZ4|!! zXUy;P$I;G-kAuIu^l{+DKOR?o(i4F5*e5WL*(b2xx}QL~GoJw7T=xX<_?ahwZ(mc` z!ub9q=JUiSQT|K~FMkqvcpi9ZW>2B~?oR>!GoC{IXFUZtU;Y%<`yZYHoSu71>Eu&7-%nwlR(=}a zKYto{wdK<~ZyN6ZH0tSo8vENxPouwgJ&pc6tmR&L8gTpMY2eXX&mi1^!Xnr64CeK* zX8`YiJ_C5J_bk@cuFqn99P}*a_l#$e|L$jDPkQNDz;om0kZ=5RNN;-%?HvCc@b%Zv z!C&K%=g{x3pTqiI^Lfn6Xbq=654argJn|JaJoHtu{H&L>otMLEed%kMudiN1{TuvE`G>y&kH-BC^rQ7}@L#<0Z{V|^ z*Z6f`2S2;d>yXEeeI59<_;tt+uf4AO;TzyX#=HSLSJxYmt8ab-a`2~bpuYMy(Qp4v z=s_-|a0-QQy@_#e{}$$F>RW(w<}JXt_!i1_Yy6dOVVt+Vg>sL*1-QQX7S_p1%P`I# zEd$&JECbxOUZ(4D8Q?p28Sre;GQjWpW$@Sd-7=l$w-N6DHu^F5ZOrFEZ>xRyZTM@P z_BQGr^A6VW^ml+CZSMeHC5>P74*K((chrCS9h7@n(?5I%__NBpSift%i}tsD7x=o{ zyXs&3F8bZ_F4n=kcd?&$y^HZLd>3#z;$6V=ymz6myHWG4`yT4q=sk?9{yog&cJF~s z%zh8+-g^)J8i&7!a`WE@9X|AZjDOMl=-&`^4Uat60 zd=LC5;8CaFyZjUW8WS{r$v**?rT+vxKhS*N{1bf9${(Pe0Uy9$W6THe*Ldaw;P>#4 zF#e{GFuz$17kmVKKKUc?4Zrya?ezN?`2MqxfiDw22Hws682vuyWA!`x82xzQWAtOm z$0+~S$LbgIG4OizPXM>spFloIe}ehGM&s}P1o?YD0sNl&1aMvU3EKJS6UwSj)ZTcC~xA{!{_df%kP5KP{^kfYW*Yw*y13Y>@!#q6u8SH;wP&kdk_J3hs?)Vqh z$D{iF^}ke~{yE08;pa;KKUaR~bBu4F&p}^Z4bT1@>tM;}SU=Bwj{08v9OLVB@JqmX zqb~u!t-e%0oG-DicGvjKm&o6#-=}?vb$;oW823$IV&8c1OSK1niGHr~73lf~UjZ+6 z`U?Ei9{PRISD5c3zCyn){YvGzuTcNvn*U|Zzw+1U$Irh8T(H{OqyD?U27H%(4g7fTYmED&uK}kYd;|LblWzdm3Eu#&dwhd_q`!e4zxWOOHSYZe z>vFABKk4si3VC0dK_RzuGKH*{y^z9j6uzM0CjI)!{G=)5{^#`j7Zfu8emsTT{w)-; zp7=KuGXDSM2mPeK>-+%i4bX5W3fUjKkwV6gD=F;9>xM!e*F6;Sd_GK}_&;m>n-uaq zefR^kzt#`?$#^%QkmqY#3K?IgQ^@P{I0~6>yNp7H-!cl>U*mlWc^z!M0@@k50@|6d z0^;}9a1MpC&#Zv@OB6D{@_#5~f6#YUK>wRpMENX*j6VxjMEO%zM8D5k5%9fqMfCq> z3K=gR*YH&e#XdkGL++nzY^d#ekGKjP9gK_Ei0kiB@{9py?G_{@0pcQ|Hl;W z%5Yy9_0FJ>`3avw-iI!ukol26t&IA=UK#Vc+A3(*p^))+dkPs3XRm_x7g8wtHT}L| z6_mS-%^W!0AV;_7nZ7vnuM{d{yAh_*IdwfkNhQ=1|Cd(s`?* zzGpQ3WeS=8e4=5hKj6?`!wvdlo`?3wyl&GUcrcnmURV3}M}1|DKeRu_c`k*_=l#Av z;PE#KnQng2AMhIRqkgh(_Rz5NN0_Hee+2mU{0QS&N+Ih}zWNd7W7pLX9i3`)k~y`M#o%_u>9|w!kVaOgEcWv6W0Vh_FoflKV(ge=bSZB?%_27mrvG2f7e;7AN=3f z!uSrLkm*{d#$Ue{#`ze9?62{`TEM&f+JMjDYh&KeS{rz9;o3<5_1b{TeQRS~{&j84 z|34^XdidGez@vtBFz-$4;M-jX>vrBcn71wskJ5anuY>k}rSVs+12`jH0D*9F}=c3sTt#hQMz=D&Ac(9tI-WIOMmpZ81cN8w=TtY?3H!1=KCfsdE2 z4?6bb`bd9aeT?^=_0isE>jRJaZ-Dt6v;p8YVFS?Nz4ZIo4KS`>YPe_vjQ3XkzJCMI zt*17?diaP!<_kC25MjfHz^kqefiEX-2zqwwhQP078=_w;ZiIYmQONT0;EezemqM0D zx;H|<7H0pa+?af!D`vjQoo?#yWYFLe_VEx-s^b@ta^C zPS^zfIDHe~$weAow+Zm^x0?W-k8Xnf@##%4{=aSlynJsH;QJ?<|K|?!4Ruh@)(-aP zT^;oMPz}#^FmE?H81It~>Uqb(y!?1m%)?fjVw^i{igJ5xiuFBrQ_SP3o1&iUHpP5A zwkgK@cg?r%09~g8kbb}b)W2{5@a6mg7{?<6FwUn2fW9vsfc9V2@b3eFho27s+`b-w z^|In-pjWGJhIPK(W|;3AH^cgRb~C{HADdxaY_~b)>Ez9^K5p6^<6CVY=)x8QF>j*= zf*#Erh;esn{HX&m?rZe>kDC4}g)CoxK_TlScijSTpSuO{=&CKyuUEG~z5NIE6Zvn; zL4d>QgMc^pQTQy+>mc;^4}-CPZ#)F^I(rDi$-;P?6vz-<|Y%;$YL1oN}omcYZzmRPq3ZHaLnz9q(Y(UvH8`<7V8_il;(^2sfM zcQ0;L63jB74T#7Rv4eZ71Gb!3jMrkE8xjPTLE5w-wO0@=uoWVDMPV7 z7Ys%Hrw;`^yKpGr|HV+$|Fb%*!=38TPHP>?pI!&L@w+;df3yzk{P{Z2gSG1cw@LNb zzxJ!gese-S=IOS2^yle%%-^RPZZZtxo-_>fXVx&}KVlg0`O;xnr`KxwUBgiBwPC=I z9}Vx9I-2ouIN*BcaKQV4;lS@#hhx5$4F`U|M`K6FXpDKiC0$X}=xO|7~|fKabxL`1!()p!aX=2sr&n3R6zKGhqae>r9EE=GJ_>l*GzxgzItu+NYWh*5Ko3qGg?T)4 z6zIYQqp*G#jRHJx(e&4~+`F3ZQw_h-{44K_?{#+u{%o={#yNOr*};!0N2}h!8jh*{IBeSeto$M+FfBZ($^b}ehnE7{24hK`5H9bYc$r$zM}!} z*`v{}KN|G0JR0luh|$2ulQjOJ(HO_mqcM)96tcg@veBT!?`r%%wZ5-LqhCK9gZ}({ z4B8tq2JMd;gZjpd0sJP80iI0Le6z=Bzs8{7WzDy64ElGB#-BC@?VmFSbnikf|MVE} zBX5lXT(;X4aGS6z;Cmp23n-jN;dvCkxhwjA#8~7%Wh~mcXe{7()mZfV_OTe(onz6T zKU0`;+(O0~7&v*q=%oe@E(cz5NZ_RXeBLXRyo}=)oOHWeX!8QEMMF}*`VYVsX(^i?CIum*;2db zR?i$zGivZe4N$Y#8{mhL(Zos5+&2!A+ZGnwdPyqEJz z(%?itm-7J!{?Ji0@{COnXRIPlBBnPrg)o>NcGqbu`sEIqtf0NccZ=0iY2-XgsiukG zn{Jn1B^rBB%BB%t&J$E+_{}b|x^2D$SaRm8Tx$1=(J#pvTU0LR4p(7)MS2WB2Mi1b zm>k)X<^Tk!0Q$o}vH)%?!yk2L%y*ECFyBrWtu5|Mwm_?emvK0l49^HhR8-Q}LZCq5 z>UZPAYW0g2PB{w2YO7TNC1A2jWCN$*)8cnKI;eKao@sG9ykfiCK|L!`P1IpVUIrL9 zRdDn4v$g2w9ik@~Qa2Hrywj2M+`w~+<$|P8g}H3n<#EuIxVY+Pa@R0YK(I*b@RkV#!GTkwX&f2VVP;AMuS>gt@SG*p*?HqWW6ON|f`Gy;@o zgp!u+LTWR%vB8<=5pfc-FqbkF+#HsM#B`KfXoQJ`7Qb9djZO2gCFms3@ql@sh^VkY z;GlB0=s8VIlVuh=%0W9*2>D6*3T^dHL#rgG89!PXm>$npJ{ts_lcy&uxKN@V(71MQ zZfeY1B5_*PG1c zj-2mibYW!(oas`o+v&`@5v(O^F+Q4Nf^cc%a$BU7_@qm0*?=KJQ~vZa`0IFiH=E<7 zNySZG51p>;D(}}FR%WNGJzMf}L_al^;nhxC6MYh*;;+>m{_3D@oL8@xXYhB@&c%Ic zZ6)YUtTh5i3@(6Zw15~%?rrRqfD{P@C%okOj zZl?uaunG@lnnvxm6EDNam@Wq;B3PBJa3jh3gRlXj8>Mg4z5i6lh&X<`K3VkgzYi>( zUS>Z9o%}Av1#UeefxP_@tt5QLzC-*JAxFJ4w%`}K^L`oRUH&?T)>~sm&1M@V7QxTc zUX$jg{4#N~E@-ciVLNBuEtK6{&1}RAGr)42 zcl~s_Tx6y@QF-yKcxc0teFBb@m^8k2S-PEg8v~;oH zQ)4@_%t1LpS-x9oBDxJbSv^q@s#c=VFiPqu5{E!}NG=H3KVk(k!ll|Jkfqe!;mI!+ zvCYiKKApx~xh=~?B_7>mc+0U6M#frX#?TF(NpC($+J%U$q{em;lZYzZy zT?0usTl{Wi=KEwp1ZkRP&c(fCq?+OtX_~V%6y`Akr;dQ`vaCeF+)am)8dpKoET|(j zpn%YVzX~j0xP<3z$}C`GBEf>CV*-|D!PJXHR3Zw++X@NoC6XKnG^G;PnvpdYm=dy> zJbQ;?M!K8z2VSm~TX2O(8s~P?|T?L|WG~J2C zSZ^|L%i+$_K|}5$c_*HjXxgN*GC`FGkV|cjHBvEzznoUutE|sYN-GHm;Ir>yneSLk((zwV^p_$TmXb3DNUDR=~3=ZVN_%Ku)HVp5$ zc8|x-{o;NS28g`DG?FAKR1}n3WU`Q%JJ2eU36rA$eWZA1bpk?xG~r(>Q43;3B(HR% z;H5+uqvfD%6@3evhP7fS#W)hNS>nxk5HK+{Bv}cM?b^~*IBS7l6hhivw zi?$mNoYpv%kTs0yneE8RwWnzv5M#}^uo?x2H6hM|5ew^0d{{uJFhjN+fOm0%ZX&w# zL-kZp?&u&?K}n*_Q=ld`pV~X~nUAOHrzDFmR6|R-8peb(s}a*_AYk=P3={v@hv{UM z$VS;)WVbYl#fl2Un4wOKHc!7y*BD(&Zd*_v=I5{QL&02V%@*@e%7+wRBbj7iQE ziG}zYX~GzT23OA@Y-n#8gi>&ZaOUhS^ouI~&uv8c>o^C~n7O2iC>g8C6{+ym0~hrs}#YGf974aJI=Vt9;%|4$$Rz ze>=LBiPDY27Lbt|@kYWn@JO^oQk1VxmZ+#gA;F8xi|N$Fyx~O(MC%(!kMG7J)S0x{D5mTn}! zFce&5xN@|T9T82d-+?s>ODK;|%;GN8Gku}CwrCT+kRsS(QL7yrjV)>wwwHnLl zZX~E=qD1x{q&i1fFPa53NzA0138#h%l7yJ;(0L=e zR)Dw{14K|N`rVG7V^eO4yTr0uI3N|=tRa#}M-nc}E73m6Mo=bl)5DgHAUxhL3}OL? z=qIsqM!Fh9@xYSshZw&C8E(j@2hMc2EB1YGwj=r$9?yKm1#rR2ib)T%hI0A@9xJqb zJo>mn&Q{!}iFYp;;X`#Y5S@jc_cHZtMhRt&qK6)Gos9lzVg1n%8>Q+~Vk+i8AfEE8 zF;XeXcZJzTVgu3-vTPAS<}Oj9-TFh{byJOQ)} zap|CXR&40p&5YTjmzUA(e#^^e^Eb=OTMbeAlzTZ4jmq>szlnU`uGWxg>?OBopDZVh z(2-&}Wr$RlNxBM>rRFn1iLJ0P6xku0S6n%uv9kNp?<|pd3XKY#RrXcPbCjW|bRmd+ z#P#MA!CXW_m)Oef*o4kFHIe-`#NUe5&9dC(OS&h&vXKfh(pDmg=@RnuFWR3)G2P-R z*(OQ`uLRzs;JF1)Emy7a_=E$EF-!3lS&WM{O!3OZV6}K+pJZlXtY{I_M(HVh14ynL zYV5F?h^LLHtz+VFD{*X0sHG|KMak4tcZ#%>rqWpOvmn33nM{LF)Wrs#iagCG`mEj5 zy(h6VIeYt}Q3*K!H(@JsvJq27yJj)l=D`dLlEJmc810sB;~oKF-OCI`?L5kW=R%Ts z=qflt3?lCgsexV?Hu^aTPwqdEcW%9`bYgBh!b*vu^p z^4cpj8qi-`F_D^-^IN#962t_#s$$*ssW*0vqens9b zbKT#)(FFlX3VClK{~pv{Ds>EEmP>vGgW&KBwN|-M;I2gqY7BkocW+s^CutaKP`p^a4tJfoR`~ln(JxT8S*`v4YCIVe2&9EO_SL?J4uVT4C`&@ zcfhm|dPG)Y&iCj;!7CB%l3viyE+!IYml&oEwfith)SAc?1V8!f3>Y|A7>PMdp@swl zXc@3xrJKfq{NraK`l$qN5|nDXX^>zn~*=oq#9@->@(}eyvW?ZxIw7CHDVE%oQBqM%o*F5N~(Qm;mXpH z%~It~w)P1R&=UBfhZ3y7Fy)o1dmGY>bh+I@!t1bHVD?5ZgKFwS%but)S%EXI z!2!U7p<**EbnEWGP|=?7&S8AlNVd)J76Y0@-4>v1L)-&nQMatbY}#YMvR<@B9566B z6h#$hl^TZr@cRh=88v)LiyB4osXFsm`V4t3ZJ z3J%py;{9Q8Fl1QJS=dT{i=Ea~z*@eFT2<*w>zX;eW}23R%65_z8lpe)fj{wkn&iLK4X;yc+eh?8|VX=r*y2%%)+@VI--P@3NYFP<$c5%|r4x4?}`@LYvc2(153TU?3mU z$|VUQNsA$n-2nLfkQGg{WJgmM3M3=p7u99^0;Q%Hr_)}Y#*i!5ZJRHnm63Eha;DKv zCeoS;P*og}bw=d)MO1xgXtYYOuN183tbS8!9`ZD@z^1UD8P=zpkuL?OiX)~pL2-)s ztMJDR%MLe1y;ve2vk69zYDZc#G{q~qbd0Q-dnuW%s-?R51O=w2+fnT^{hI3Qi41hUI}+QNXwkPDm9n)?{Haz@I7oAZ?Jzw> z)!HdpvHXXzy9u5{1kmXo3kOK3SPDX5GTF8)RTLUu`G=a6<#%j^5+iyPn|N8VrWC%Q za-FJ9Moc3-`O0?0DhziB`-6MQwrn?SA*KxE2$=z#Tr8Sw^CL@PYO1ft-{^;72D`nI zd`9ltI#}Wgi8lugi)RoBB$5qPi+&P7O3=|naqMRn`!da|>WF^|bH(y4pXEfV9xOAT zMxkwf2jLHqUx?f(J)6qzRV8*yQ8zvl5!zNH2J6byUa(OU&S9EjIRg-*ku6|owp6Xr zra)1UO&hOAjHQ$cqYHI_h}aggTx)>`ht0<8l6GWsX%mK#zr2xV35o+*P%egEWFpq2 zVeFG*1G1!v387*i!O;sPiPRWn)I>X~t~N zKf0JPjwGs313iuXb5o7%&c^4dX%(`+mhs*R+p@J?plZV95%+@{$$0#{01+Hn$XiW2JidRUWvwj22`wA76r z;gj)TOIb$XMtj8Bu|I$+n8nm7zM}{jJB}W6pODO_o?HH3*!6gF%dk==s{g z1=>^Ql>9jyO_41`O<0e^{C=p_74qB&n{%VOR7%Ji>u^76EN0~_vpP1VVh&FBM*yE- zHTakmKHva<0rgN`CFnJ#BvrOy7K^@k0@(gt*6$$p5r+;E zj6ByEKjsqu#F(-q!*!dKnm{!f?2*LIzBgJvf3c71hld)IF1X1Eb7Z?k6!ti7UMo+P zRC7*T9rj~sYOrCZUG7=Xvu%8SZX3}DROC0;BE+KAQ$FqH(&d~RY8yKJl9$LSZuijQ z!Rft9r#O!`B!h;mP_5y_SE%EN$3h}&6yr{8u z`vXo>$}j4fwkqibzn4TgKUF&!%uKcP#Eu+G3-yGt*l=CMVv|Sc*hbByo(aDAeveYs zFWk#xW#ulKVs!MWdTN*QEm3N>^^=Vb4E0KL12fQVF}noisZuhuR%Dq|_d@R%w)t`& zA`2Rf?M$TD#teUS>`jjN&=Wk{iKz`MwHq5)!>E|_p^H3ktR+z^i&vkyd9RfwX#}E(a~Fm4Fy;zyDPCC{}*QP0Ism8C6f5R6^efXu;a{0~f zAT%4%NAu*S@S`XjM-#Oof6S#{_z0B|P3(T*idn?i+{E-#DwfkAXl?b*AmgPma@ep1 zT=l|Tjmdx50-mmggNCw4iXIs6B))#+_xA|-FS~=txaf!R8xzLN!13SU8}VHoBfdw| zGBxz0wQQR!L6g2`wb{%LHy1UUFSoEkea)4qKlIv$)jFt2hlFfqt8M{{=^TuNeqOWk{iqmugQ@3 zj=1(vvLQuGvRcfiC_#PM4hm^c7|14>8P=2O%|6f=n5z=3b)@gqlt~+Lv@PXTwIxJ z`nNCmp&k298CbHiHbTdx(A4{@E`JsXJZA~BV&0TLZk8A+1^wF=ni@Y{vaxJ8U9 zmbGYLP&eA-*TYHXcQO2J+2|#LIHZR0;ZLy(%12eNs+uY6!i-eWK(PB-AzR|T-mnx| z>oTu+&KxZNy=3H;L{Ad`jOIj?fl*?`)t1$A;s(FyVhf3sQzP=rHgqAz#yBUNuDnJ| zv)Kk$JEl+NhM874BQdvZp)4gVW8xNGZ%S2DbyZ0MGb9Nl#d^m5opqZU8JTI=ArbdT zh%d9GSK5J`Idht7r3IYm)QzTK0`k~yYaF5X0q7~0ikKjba-H^ao4L~?+tyyf6%YaY z_OXYE(GAH0K{4^YYp2O)6{f+fLTDI^7GH(6t<@)fwn(t$`(zpl2xoMd&_I!g!WI#^ z+k(I9x){|WCmIo*&6-V`*PGZh>=KC;H~QAlfj4;|ut`0jqa1Y{SMpNUrKi!)<)1L* zyn)l^GKFM?j6{^prJ+1s1A|0d?23pc@eI_FVTiVtDkCi+xQ=YQSRAo=HrXzo`C3_im`a5n(4>n@naj|HO4nC z(Oi~Gq2Keksi9L==s4lj>5UK~LP84G>{0p9Rhq=uPB+JNji!EpkpKor%gHO4U~o_i z2r)Lza^V!4j#Zx^wnd3H{J+q|!7W6XhJ-z3;aurP5sRhO8D6)|*6b+B*IY~P;t;7P zw7ZA}T)_j+JlZ-%QDOOaXUZN-wmCMFvd&PhO{v$a^s1j&U2x%Oj_U9V;v*!NbjvxF z(3_lZtIq0KAhyu+tuDCN*m#N(M$szCVL6ALm*!bUrhf(By2^yTB;rYGEv`&4Mz2~4 z#_J`P7M`W8OoC$zMb`^1#*+N1eUpv3GFq(pQLG?>-ZUT=?5YG)?=(g?5$gp4l8cCf zoW}L)Y#Hx-!rm4bvJk$}|%0D%JCbLIceW?1FD1r14&)Vg7$8MpLr7HR~ zF>&*ttUK=s>@&wT8J}*sSJ`&ow)co=fyoW*v8$~!KBwl@j}jf09VIKK47U*ZbS60p zxwmf=SfY&FfDl-iKvlX-=oqi-qk2J4i%HMv1PRP`&_9ysQq3f+75H{&_=hypo?peg zsF{SIWK>a4=fb6|nVl^8PvT%JD;`8BtxwIEKAHdV{81NXz$+oLKqijTn=7RFM20iK zP8tyEF{68}xjGTeR3ZmDV--BN<;bpUqe6U6^IChce9DBsEM>ptrW+|r-8k> z&M?|t^COlBM^W)((BI&{aebRc*&ekackT>sHwScwXhy|HBkh{Vs>g9nBAousm+e$) z;;Pv;tE5Ff6IHGeHTmO*j!kThv%fPs+KPM~be1NAcD0Q7%2TYI@{=2Z*lm8-5U2HU zEbh8c`AM9hVg%6K!yPSTVeGgnbCfTLJ#HaM)<8Y`$Z&K=c@?u(wM1jjvC^tp4WeYx zwnU%$J7z>*{$<5A%GAELIP$QzezGlsfn|)UNmGQCGiHpMQK>4k<04av6=~Z_tmv4D z!*&C=ekZj%l2p|QJHy=aHNz<2%?~rw8b+5|*|LFk17MiR&J!oIVU|4YJmw&WI9qx8Db_iK=NMJ610QpV3F`!p+!md(!@>Y^^Uon3I)toZKjUzR*R{O zQZw1W6Dj9-qoX(`CaIY|?plf)a@2SuiPi2q+*|yjGpW5jQI=%cx5Eu{gj-e8J22FG z>Po7o3I-KfS5f3cNhhm#s9JG83M?c?IDwb3X0n!p`ub6yxDwORRfWF^wnpg}|JCuDlf`x^c!*?56lC zP&Ps6EndPT(bg{qyP=CWss&~YOm3V;i0;+WTL#0uxW$9=2&}B$2NW;und^$aRoOu$ zc}K^>H=J3|mIm>d%fdklS{F)ec(t}&s|qhxMa_ioRJVO0;CHAb6WxgwpXttUnaP>j znt6lR3IV}3THVl#s86M1PTbb5l2RIyfow2E=mmW%%TOZ^0ixMbR3_oGWIbhNzab#` z4HMsjW3*vb0js#W7Fj~qs}m^eaHza7nvT~!d zd4p*}!pcM1a)a;7gsY-fCw&JH6W<|=-*kx<8f#VUO1zlze%(sz$Odg&L87Ozcx3gL~tNJf+;oYRFU=Qm~poQ!Q@B_~NI)3s_fw zrz9KCeLelm`@umHQs*+Z=7=NcNkKhTmtff8-XB#@F}4Nuschw4 z4ML~!SD#{|4+gfmuwIn@5LX8dCO(~n1h!Cew#51RFeapnS^F5gNH9j^4js;ASZrjO zi-VnADdnO|*^X4sI!|rxgC{|OHYi3d8GdL!dNh~9~Ra4Ni5m@vL0$7hZ!TmZUL34Oys;*}o_T@DvxqEpcP zrDD3O3SKsaS3$x@Aj88sQHQahQhfYQ{)ibf}|<|Z0&Af zt~%{4El8D&b}l84xB1Eh$%)!>Av}C9*urlY>YX11=(sXETcM5CRZ{P$T}b98u%1>c z@zVma8bmXn)H43}1zoEP=*}>UB;%&yE;S~Ja55$(SN6wWVGz9oA3x&L33Uybx|t9` zM>^34+n+rei>10LL0dLcw_CX_sB88|I>hr7f*jl~cb#W4*9GZ(yiBBqkTRS6m8aaH&y5ZXnA5IzTj0Z<7-_~^_wsA&mJ93+Cw;E3W z_2-)v>YBAtzc`XWUQ83KR6dxi}$mVI9Llhz!eVjl()h zb9S3PY)JpcT)F7x>LwEJ9E@}d9r79Mvh^qjKX(~ia7H^LhV-A(Fl9mnk?K6=Z>Fn5&E%l$I;wDW|_ef_q zK6~yAuivSD`~E3Mj@`-~X!eV{R2y^amaU4|#OjaphFN3GTh-i@H%)`{%XNPB3~oy? zTXxEMs;;vy6)J~K6$WD2vhOCTlHDutxkK&-U!Rz-o+AfAwh^5|9H~6X9#VZpO8Kq60cZ*jdv$ zF&Z0K(KT{&Tae{xxnUwOMsI#PR}Rd?RI9L$MVX#S6^59^hRo>cgkn?AVgkHW;dlY7 zC1b0;J~gc(V}YpwRn&6{zxC_!h+N;R*$eQ<5zhZn4r((u1o_II!E6^$!If9`yqXc zKM*XGDZ}@}Vp&v+bUJ!|%j~aj9tsw){LgzRxWp7Lq*VXO*Mbc(Ecv`rcp>9VD1$dl zWVG>P`%{$0TW;dhU}UTY<$jB1+aWN}a`58X^H>4icKNY3v!q$8S2Bo7n@a5AUQ^D- zUMsq-Snl9=YZBOPm+P%p)t??VWy?W136-!tlNPl_ly8E0k=PC6m>NX&DEYIJzuiN{ zVKJGGHrCGjspvj7+SpR#bwzN~v4mdVF!n(0ElQhe$haAHeqhqwY_JF%K=|pgh~o8J zNk1DJ9pQ{b1}7w``?8>VY&K z)NGxq$Ygm7?bArAf$Bfmf8q-NQ{85pT$b%H+7!ATuP5w0ZGBV!L%j$7!XwV0)qnC? zV5Qe!ES$pi1G5|R+zb4wwc_y1GRG8c)BC+6b6 z`z$jLuXiG4?18;K%FI_&7Jc09<`=NBSAUn;utqJ}LY!AJ5xu<7JcR^l7ec)}(acPW z{E^8Pe9Mrd9yy1z3L<>s+<$ae5Rl7xdy^%hcCpF*JM$|*^Xk* z;tm?H%`arU1h-i8ZRfFUQQ&341Uduqk$6Zsd?#s28GA^^FUT@VEb!$#@Eo=j(6ZDH zc=^HZfP8FH!cDf0hn~ot9(z zJG&aY2dWn+$cbVR4XQw^N*tb6svgfTMl&Y_mZ_!4dtFfB!DUd5+O#{DH)CWJYvTi4 zY_JzyFMEk)X;?*W70*cfc;O3Y2x$^f61oLqY}~+(uh9-`PkL!cUU1feL9AqmHU`5y zC#J{>2S|HOQk_#UE6*@cOdJ?!d;}E(U{^2JkF-THsBl@v(h&-g%YApcmG$i0cUhf` zHN`A=rm9a*8)9hKTR#Yy4}R^BPZC1N_+yRlFKF3Hn}3mn_ZX1j$Z%ws{&$0OD* zU+7t7R{)pJFI>AF0T1W@)eG057RUM>Gumi^sB|x>+JBq4PC?($%rFiNDqg{! z?nOP}c#-{L6y6wZGM+g}t5Jo(iu<>`j~(r@m-#7U(ul>XD!MQ4WgDH8jN-dJnC;?| zCrtNlxV(ft{BCb&>sq%2Ft76c>}r`rd{|y4p>re6pF}nXPpoQ?7-Pku)^$r|*}H9V z{NMTpcXEqK4(H$g7B_ELwoF&#RAyPo9cCVP32J8N|AZBh0F;!9klXN;5= zb9%yP1tV0AXjRQjs;)haO7kIT`RVEb5;Sk+m{g%xu@b-CBi)lk)g4!B zr5Z^X@&vWn}jZ&6J^ zSxanPo6o%uLajj(#L36Mt8)V4k)3O2t9|7=;8eRDR^+uf6?%doATfh&v(WF@Z-HAf z6E>g0%iV>&7Ax(8eR?e%?6xu0a!sMCGqkw|J&SFLhy^w&7I^B+P_Uex zM0m&5Ip9cGzc!(+k8g^{(7w|>nC5hMoyTJID^fUEs8)#4z(5^i>a9}ITjNn2UJ>Vx z+ef0SW{BP%w~~bosUzVed=0#yVtT#9su{u`0F=#2m#7~`#tjXY{68Dk1G70N_s|SG z(0~tLZo6@PSt4_6)G-Dvil0l!pA-1SEh@`{E$gf*pC~VS;KI%8W`G{Sj>TBg%iU8EJxKz%u39v})YhPY1XQM;9f}t|0eR;OL zH+zf$HHZ{4QNmVIkm*>~%(OslZ8eeA3}GhN#@BQBhrFaD-W zWqwg&hn$e9UU?+paQgTbdhLEEDqoJ}t7f@xV`{4?`dy}{qLRMhRPDB7c=hexRsS~7 zO()phOw1?l`&H$cD;YFbd>50`JiHtB{t|n(XuZYm+V(WwipwP^@WPn5Rc##X_;S}m z?+>#RhX)D-fnB|VIG%NterWr#4L*3CT^z-Gew)Ek2t9w`l56o0%9d1E4pak@Z6V2E zs-G9Z*{WxnQ^2{vP|qG2q~s;_XeV^UGqC6x2QO2F`Qf>(ec>K{9 z4?HE##zhSr@J&Fzl;wx~|FP%YCj>-e(`=FBW25aXCWKLJT{Mxq*-F!~ac!ws54fES z8=3-wN-0aEgN+6(`ep^0cs<87ue-&oNbOcu=Y+Ukq_3~Q?-uHGl5$_D?Fj{)xTE-3 z%U}0fJP#i}4nN*zbfDpp<7drY9t5y%Qe;#U$cmzT->r<9ZfnNQ#v~ zBp!|b-}mDG_r3UU)9n9$-iv2L?=)qT_D{TOu>SyOE(w$1EbRBZN zOWa((3TMGi>8WWss$AH)a!!;N0biQn#V>~moK|BpZ7B3ypQeqtQAI>`+BACD|1s~$ zPbh~E%8RC3pOcR{BFA5p?>U)9?&+KIA~$!q;=oJ{g{biS|9xBjf8Un3-j<)%VRPuL zsttGUp6iLpPkZ0vt@&}0N+et8?71W-ZXtsifz5mK1?8#4C&FZMhl(e!9txuI7rdS; zT~Xdzt`k+?ov;4pJUhrSX$T!6qo!zuisrA(&J8Xtm!KY0DeN&9s^Uc3kaQzftEJJB z#rd{|<(NKWuhNe9VmrKDlwvqK20CG z5D5dvvZ6>r{7^l^WgK6#6AC^quOVi2dlp0Lk&6zB{6IYkb@BJ<+k38WWkW*Q$@E;` zmgR#wHJ_*t%|#hL+EotxRL^<2677i2SYzWQe%X4f9?2@Cn7l^68>T{trLD?DX}(>E?O+9Q)_FgaqxD zSfQ`m^L$1Ur^253Y_T&}JZLY`v|UubXwUjaDIgDh;YehYOQPM_(CxlxxgruAxr?Gk zfbm`2V8R1KeJDiRW4sW$;J9skY)(I5%TsfWtzJl+5(sq)(Go)roVhZKGgD!F;o}$L zE;^s*+J(DwLO%s1xS7!C%%O3-vsX7UcN=AR5o&1PTl*` zZl%r)Ig*tQgcBb8uI#%L)isaRENmH27l6<+I4%}N(NnyVTi5KiwTZJUVY>KUPtoIn z;J3{sw<^6wCe7IEy!E}8>JD#Xswlaw7_~ABlVT%PwL3D|HB7?xn zPHrMPmXG;KYr`>0&o*R|tk{OE-HN;kO++mpXz^9Ax3WRmm>dwy-fHw?EK8(^$IZ2( zgi_H&SN|0MN8KMh9lR)grs})kd@NBekWZAee77|vFGK>PO7^i3TWaF4%Pm;0NyHZN zt2H5vW6t;df+nl4rD|<1M3$&0^--FwjkeMo#?y+EN$9zRFTp{682E*22+jSpw*w4( zkBU;8ygV;bHqV2rWXocRIT9z-t4Q?j>h6XKMKVh@3mEe0#*Tj;6L1 zvl$i(_!cUTqTz@@log$BSD}9S)#Y8SE%E~Dy~3W~=DlJSvk5P19K{IAasf|~ovOUb z>qt^##T~!$niBX~2lgHRp`*8;I*o+=-+C(EhG9#0&W`*!t!6Uq@=K8_DqD5&`VFCb0Z@upUITPx@j+huLCH(75HSV(j)C!fn6g zSM-)ojj3i@oqno!oAVWw$r0dKnkI84mJO!Fmr987IHC6g!#Op>s5N&JNwU}1DKg3@ z#CAqiZFjiodCcvYZ=;M-wL8frmvpdnYp$BI@4u-M7a^vY?$gCG<1JrWW=Qn(5V1QV zVq?dK>mW7RWAY{*$|4ErE*n1dF;bw>8rY{VEniamOs0%KT&l4P*~I0mT=MIp%MHF& z(WJ5?EFAAvDe9K^UkmBhqg?bW?{-)=e;PV*_#R&#$LA5V>^LunBBqBA@W@Z*SE}5r zW0I=Pi=<`4D`JZJX_GQ7FW0}AHeizMox+BMRmJlgNl1&; z%%}D8S|Es)i*BFt3X@jqHE$)m5?3!6xAe-C$+1P5sZcV<}WCfs#m4J++GkP1X_F&8KE0j)kdh@_g=|+`H)Wx9$_pxJNmd867^6g%xKCHCDJt90#;M;JM<0j#JRiD{# zNwx@^-G>70hOopK+SrMPOiesWI$+1AuiHE))9exnX_vJao1dD?CPvY%`a-u;7C)82 z5v{d7(D>=5S}8Gacek<;>yaHews%!|pCV?W#0iRC8f@>qIlZ;|TeViL9w}etDVv0M zPaICYB_=@Cdsb_Z)#+&MS+8-`7^~4DN?GeZvTBsFMqVNdH5LPH)OlWYRS89P3R|O% zT4S#yyfyBzO5TLXtk=MVyl-8NSW?qUEL|g&jkUZ5)o4XPK|q5%Kg*XHa_02>XnjZ8B6j?Z52mCgY+X=H&)qnGHz)4SrwW)#>YdG%Zs@KU#r` z;YRvBN5nN{GYg%D@$pwEhbEo5#HK)a1l-~`<+B;0lL4#S7(a2SRjz7g^M06Az>(wK z*oQ=}7OCOxp&2SJ>q|8gEmjpJYD8ArF3JT_&o;@qJ^OL)P)F_A$Fp#T7Q00;c?>1a z7DQ(cLuss!l_pKh|E_vtovm`nyJpq$ibhr)l5BrnbwY~8nd`*xWR!X?@l~Ei01d^? zdew8g*6lPC(L{0(K2i@UR<1A6nx1yV3>2w<-)gT;9hE8Xd6n9B$+yc z!+3?dig!26MrgUx1^oVBc(ycoD7zYuRYBL;-DjwJ0*W7pW!LbF$z##=sVROS4k}cz z%NZNJtb=cP^fkbT_^R*Dmmw9qO)=3vsYhGnK4lVPs?JayCY8ak&#xXvi#%QRN+)J_ z_{=Kqn5`RaYS44TrY*J*vH4OHOVM#WEn-2@Is^BTIc*z5v;HvxO<8NLvsW6FPbp2Yh^m56Og}uWt5r=FDm8OCG0g zGzAmFtW|uKk;I#BcyE8TxM*Z@(29^KUnX#w^IYN}m-9NsjKT3GIf_C%k1OZ2BvL&4 z%Edq@MBK95vl%gI7@?vN+U6q~Tw$MY^?iPo$hg%Jp@$K;E+F?fl0ZwC88m;*XD*|pg%2Su(ml-^f zDx#y+V-uI*ByKZ+cA@5V2C=%>jOI!9k)ac1WR>CB=Su-%&NwD5cCDA?jAGkA*kUe+ z>}n6Xsnnh0mzQW}{WjW`yi8PbQsq8Wb7M!`s1>TWV`|6n-kIvjRqmjvp0UDZ%Up+JXNq;!9DtJZTWP$x(@PF^ z+^?P-Nsi^T^%iUV@wjN`w;WT$w?dlm6nv_w%k4-t!##m#Kh=ao2n~f+xv@uX?O{Q= z#FzUKa~2**(c4HYhgoJY^n4!Wa!bW*OBr5X;uPRa9zV8`*XFpXkt>SrV&&A~*2SKy zji!TlMpF&@hEfWvCOX|5tjxYM$moE~bPb}WtK2jy3MZIVb?-|x%LT0+2C>1h$g zW~~5KJ-CJF;Sls0$50DC?yO_?WM_EYHe163-x-Lk#UZJ&#?b)l5J2j=MWMtSa?v9e zmYuld2?N8faw}}->A5(({w|L+TS;gZaG^=JSCW_05@q6-;3ONAHCDAPFU0k*j2_%@{DLKCTJNlc&#d^kwnA)juJE%MTJnnq8?)t@ry~*qAVjk);@1YHELUf~?RXQlQgtv~VS6T6~*LM32Y9b2Jwl8n06j>c9 zIt=?NthCz!Jv_gWhh}UyE<^Y5%yFUHs32LtrT6A0ct@rNadoo#Jyd3eFIM#U4itWQ zKV$qu`Isy3O$EK;1&11M&zI~ z-$$h?>}C?Z3#n%FLSu|+r)UC6B8pa7&o!(8km(HX6==?qJjH)1WC-X@h_&SR(%F}? zrQ4xBUxC}0d`M0is%fmlLmxp^61?kqm-Ai%e!0PZbUOL#GG9lolxf&ladO3^v7JE@Znfkg)xp_BG@GbxN5HrRKLN{s=f*U;unX+dOV|pPP;tMayU~6FR}TPKRqZr|*So*hy~qb_nhqsl0o%s=a`-k#vGEu!hL#fr7s1OFRxUhhQ&%-_%Z-5NgCIU zD#pEDOwI8-J>&Y|czO*pv~}vNR}*x#eAUdzQNBr4E*|aGejH^BL0rR=gy&QycWPoE zA_yC!jvSyjAIanMy=7wya?vL;kcm|n%Qm25UrY8RcBIfa&|3GKxw%$;hqveIBCEcJ zGTSCsXY;-;+EGsreDW`mM9fv{42ZCzcs(KDszTa^FAMD{HvLZ1YuMtfA~S|KU&;6J zxvaruB|z5F+62)dWns=k`>^nJo-2ZCbWe@BuoVT2vyl;SMO7)psjN@!?G2)_ z2Y!*S&LPRtda^yb%Sw;!>s_uSMZmEgXZjQN2(=rM0F7hn(oVW$(*VE7?Y5AlUi4aB zM^6^85EAn6dhsh?cAkMNi!cTgM3073;4Q3CbL>-bkwPj4$-S$%@+2L30&`7Ey5g?h ztejjASSc5oP4xK@!M8T%x9f7QTtg#D$$~1_c*!uIwl8s)a@9d0)BssBMWhdD@o)_h zPOs~AtEncv$ufF1C3eeZU~aaw?z4onBeyY`^__e#MX&0VE!SY^(C8Hwsv%u0N3sGx zP8NTXv!X_?N{xNW^u1a&mxBF!2Ev*o>)cxS9*9^n^)|`nt1=9M$L%rrS;;wjo>f@2BdWDD_Jqz7r=$>jZV*Ff`7`4qL zuW0i~EVHtcRqQ39sHEuZB7QusST&jSQdO>$kAC}Yk!dA75ec1J!RR}0Ys~B7C2u_tdN@ z{2~u^ZFXvw8aHQGo<~g0QY7Kjao@D z1W1MJ>i>3jH9ZZ(Fw{R~LP7!w24^libK{PB7+cvYZSAydAVB>bD~0d!%5YyvaZZa^B-efTF&a4fFES;C%z+%%IJ8OcD52YY;?h~aMogP>@vL_3uSOXU$*vx|0JJ{m|+ik}PglrbgUt;r&z zsXl{rI?oCG_UP6`7yI3t~b7xk=2moh*AHD>MOFk>@lJzc8fDsOnq8 zkwNVU{2~_8n2-!Zti*}E3g}K2C5qu4rqrAU*HXKzZaw1TYg%ZPp^mW)?ZJHdmsfo9 zxei#Xxqo_$Pzj!hbe&DV2i8l+DWaG|rO%8?Rss*FV5^9GVAmb_P7lql0JNb+LZ?Cf zt$~JYS;+?LAI7nqCFMW>4HmUpM6FRl)g`!#NaCcoe`!2C1Ln;qwVmt6fz%7a*EfnL z?%3`~Al@VALgCrA+st{aj|Fnj!1!gIWVvW~mQB4U)hNjf==(xepux$3l*Q5#@W_b~ z5(kpaW4;-u1a?_B}b%GMwIZ?ZPhA z$D{%wniw6_cyXIsFA`2wa03S4fmtwaq6uRm5fq37*s41zw_+rLltR~ne80;mKGJ^k TZqSZ$tejy>pi!E>2q8c}h6zKm diff --git a/rhodecode/i18n/pt_BR/LC_MESSAGES/rhodecode.po b/kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po rename from rhodecode/i18n/pt_BR/LC_MESSAGES/rhodecode.po rename to kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po --- a/rhodecode/i18n/pt_BR/LC_MESSAGES/rhodecode.po +++ b/kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po @@ -1,4658 +1,5706 @@ -# Translations template for RhodeCode. -# Copyright (C) 2013 Marcin Kuzminski RhodeCode -# This file is distributed under the same license as the RhodeCode project. +# Portuguese (Brazil) translations for Kallithea. +# Copyright (C) 2014 RhodeCode GmbH, and others. +# This file is distributed under the same license as the Kallithea project. # Translators: # Augusto Herrmann , 2012 # gnustavo , 2013 msgid "" msgstr "" -"Project-Id-Version: RhodeCode\n" -"Report-Msgid-Bugs-To: marcin@maq.io\n" -"POT-Creation-Date: 2013-06-05 19:55+0200\n" -"PO-Revision-Date: 2013-06-04 20:47+0000\n" -"Last-Translator: gnustavo \n" -"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/RhodeCode/language/pt_BR/)\n" +"Project-Id-Version: Kallithea\n" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" +"PO-Revision-Date: 2014-02-13 14:34+0000\n" +"Last-Translator: marcinkuzminski \n" +"Language-Team: Portuguese (Brazil) " +"(http://www.transifex.com/projects/p/Kallithea/language/pt_BR/)\n" +"Plural-Forms: nplurals=2; plural=(n > 1)\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -"Language: pt_BR\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: rhodecode/controllers/changelog.py:149 + +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 +msgid "There are no changesets yet" +msgstr "Não há nenhum changeset ainda" + +#: kallithea/controllers/changelog.py:186 msgid "All Branches" msgstr "Todos os Ramos" -#: rhodecode/controllers/changeset.py:84 +#: kallithea/controllers/changelog.py:189 +msgid "(closed)" +msgstr "(fechado)" + +#: kallithea/controllers/changeset.py:87 msgid "Show white space" msgstr "Mostrar espaços em branco" -#: rhodecode/controllers/changeset.py:91 rhodecode/controllers/changeset.py:98 +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 msgid "Ignore white space" msgstr "Ignorar espaços em branco" -#: rhodecode/controllers/changeset.py:164 -#, python-format -msgid "%s line context" -msgstr "contexto de %s linhas" - -#: rhodecode/controllers/changeset.py:345 -#: rhodecode/controllers/pullrequests.py:478 +#: kallithea/controllers/changeset.py:167 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 #, python-format msgid "Status change -> %s" msgstr "Mudança de estado -> %s" -#: rhodecode/controllers/changeset.py:376 +#: kallithea/controllers/changeset.py:386 msgid "" -"Changing status on a changeset associated with a closed pull request is not " -"allowed" +"Changing status on a changeset associated with a closed pull request is " +"not allowed" msgstr "Mudar o estado de um changeset associado a um pull request não é permitido" -#: rhodecode/controllers/compare.py:74 -#: rhodecode/controllers/pullrequests.py:256 -msgid "There are no changesets yet" -msgstr "Não há nenhum changeset ainda" - -#: rhodecode/controllers/error.py:69 +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +msgid "Select changeset" +msgstr "" + +#: kallithea/controllers/error.py:72 msgid "Home page" msgstr "Página inicial" -#: rhodecode/controllers/error.py:98 -msgid "" -"The request could not be understood by the server due to malformed syntax." -msgstr "A requisição não pôde ser compreendida pelo servidor devido à sintaxe mal formada." - -#: rhodecode/controllers/error.py:101 +#: kallithea/controllers/error.py:101 +msgid "The request could not be understood by the server due to malformed syntax." +msgstr "" +"A requisição não pôde ser compreendida pelo servidor devido à sintaxe mal" +" formada." + +#: kallithea/controllers/error.py:104 msgid "Unauthorized access to resource" msgstr "Acesso não autorizado ao recurso" -#: rhodecode/controllers/error.py:103 +#: kallithea/controllers/error.py:106 msgid "You don't have permission to view this page" msgstr "Você não tem permissão para ver esta página" -#: rhodecode/controllers/error.py:105 +#: kallithea/controllers/error.py:108 msgid "The resource could not be found" msgstr "O recurso não pôde ser encontrado" -#: rhodecode/controllers/error.py:107 +#: kallithea/controllers/error.py:110 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." -msgstr "O servidor encontrou uma condição inesperada que o impediu de satisfazer a requisição." - -#: rhodecode/controllers/feed.py:52 +msgstr "" +"O servidor encontrou uma condição inesperada que o impediu de satisfazer " +"a requisição." + +#: kallithea/controllers/feed.py:55 #, python-format msgid "Changes on %s repository" msgstr "Modificações no repositório %s" -#: rhodecode/controllers/feed.py:53 +#: kallithea/controllers/feed.py:56 #, python-format msgid "%s %s feed" msgstr "%s - feed %s" -#: rhodecode/controllers/feed.py:86 -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Changeset was too big and was cut off..." msgstr "Conjunto de mudanças era grande demais e foi cortado..." -#: rhodecode/controllers/feed.py:90 +#: kallithea/controllers/feed.py:93 #, python-format msgid "%s committed on %s" msgstr "%s commitados em %s" -#: rhodecode/controllers/files.py:89 +#: kallithea/controllers/files.py:92 msgid "Click here to add new file" msgstr "Clique aqui para adicionar um novo arquivo" -#: rhodecode/controllers/files.py:90 -#, python-format -msgid "There are no files yet %s" -msgstr "Ainda não há arquivos %s" - -#: rhodecode/controllers/files.py:271 rhodecode/controllers/files.py:339 +#: kallithea/controllers/files.py:93 +#, python-format +msgid "There are no files yet. %s" +msgstr "" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 #, python-format msgid "This repository is has been locked by %s on %s" msgstr "Este repositório foi travado por %s em %s" -#: rhodecode/controllers/files.py:283 +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:346 +#, python-format +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "Ocorreu um erro ao realizar commit" + +#: kallithea/controllers/files.py:373 msgid "You can only edit files with revision being a valid branch " msgstr "Só é possível editar arquivos quando a revisão é um ramo válido" -#: rhodecode/controllers/files.py:297 -#, python-format -msgid "Edited file %s via RhodeCode" -msgstr "Arquivo %s editado via RhodeCode" - -#: rhodecode/controllers/files.py:313 +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "Arquivo %s editado via Kallithea" + +#: kallithea/controllers/files.py:403 msgid "No changes" msgstr "Sem modificações" -#: rhodecode/controllers/files.py:322 rhodecode/controllers/files.py:394 +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 #, python-format msgid "Successfully committed to %s" msgstr "Commit realizado com sucesso para %s" -#: rhodecode/controllers/files.py:327 rhodecode/controllers/files.py:405 -msgid "Error occurred during commit" -msgstr "Ocorreu um erro ao realizar commit" - -#: rhodecode/controllers/files.py:351 -msgid "Added file via RhodeCode" -msgstr "Arquivo adicionado via RhodeCode" - -#: rhodecode/controllers/files.py:368 +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "Arquivo adicionado via Kallithea" + +#: kallithea/controllers/files.py:461 msgid "No content" msgstr "Nenhum conteúdo" -#: rhodecode/controllers/files.py:372 +#: kallithea/controllers/files.py:465 msgid "No filename" msgstr "Nenhum nome de arquivo" -#: rhodecode/controllers/files.py:397 +#: kallithea/controllers/files.py:490 msgid "Location must be relative path and must not contain .. in path" msgstr "O caminho deve ser relativo e não pode conter .." -#: rhodecode/controllers/files.py:431 +#: kallithea/controllers/files.py:524 msgid "Downloads disabled" msgstr "Downloads desabilitados" -#: rhodecode/controllers/files.py:442 +#: kallithea/controllers/files.py:535 #, python-format msgid "Unknown revision %s" msgstr "Revisão desconhecida %s" -#: rhodecode/controllers/files.py:444 +#: kallithea/controllers/files.py:537 msgid "Empty repository" msgstr "Repositório vazio" -#: rhodecode/controllers/files.py:446 +#: kallithea/controllers/files.py:539 msgid "Unknown archive type" msgstr "Tipo de arquivo desconhecido" -#: rhodecode/controllers/files.py:631 -#: rhodecode/templates/changeset/changeset_range.html:9 -#: rhodecode/templates/email_templates/pull_request.html:12 -#: rhodecode/templates/pullrequests/pullrequest.html:124 +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 msgid "Changesets" msgstr "Conjuntos de mudanças" -#: rhodecode/controllers/files.py:632 -#: rhodecode/controllers/pullrequests.py:149 -#: rhodecode/controllers/summary.py:76 rhodecode/model/scm.py:682 -#: rhodecode/templates/switch_to_list.html:3 -#: rhodecode/templates/branches/branches.html:10 +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 msgid "Branches" msgstr "Ramos" -#: rhodecode/controllers/files.py:633 -#: rhodecode/controllers/pullrequests.py:150 -#: rhodecode/controllers/summary.py:77 rhodecode/model/scm.py:693 -#: rhodecode/templates/switch_to_list.html:15 -#: rhodecode/templates/tags/tags.html:10 +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 msgid "Tags" msgstr "Etiquetas" -#: rhodecode/controllers/forks.py:176 -#, python-format -msgid "Forked repository %s as %s" -msgstr "Repositório %s bifurcado como %s" - -#: rhodecode/controllers/forks.py:190 +#: kallithea/controllers/forks.py:191 #, python-format msgid "An error occurred during repository forking %s" msgstr "Ocorreu um erro ao bifurcar o repositório %s" -#: rhodecode/controllers/journal.py:110 rhodecode/controllers/journal.py:153 +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "Repositórios" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "Ramo" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 msgid "public journal" msgstr "diário público" -#: rhodecode/controllers/journal.py:114 rhodecode/controllers/journal.py:157 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 msgid "journal" msgstr "diário" -#: rhodecode/controllers/login.py:138 -msgid "You have successfully registered into RhodeCode" -msgstr "Você foi registrado no RhodeCode com sucesso" - -#: rhodecode/controllers/login.py:159 +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" +msgstr "Você foi registrado no Kallithea com sucesso" + +#: kallithea/controllers/login.py:237 msgid "Your password reset link was sent" msgstr "Seu link de reinicialização de senha foi enviado" -#: rhodecode/controllers/login.py:179 +#: kallithea/controllers/login.py:257 msgid "" -"Your password reset was successful, new password has been sent to your email" -msgstr "Sua reinicialização de senha foi bem sucedida, sua senha foi enviada ao seu e-mail" - -#: rhodecode/controllers/pullrequests.py:136 -#: rhodecode/templates/changeset/changeset.html:10 -#: rhodecode/templates/email_templates/changeset_comment.html:8 +"Your password reset was successful, new password has been sent to your " +"email" +msgstr "" +"Sua reinicialização de senha foi bem sucedida, sua senha foi enviada ao " +"seu e-mail" + +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 msgid "Changeset" msgstr "Conjunto de Mudanças" -#: rhodecode/controllers/pullrequests.py:146 +#: kallithea/controllers/pullrequests.py:157 msgid "Special" msgstr "Especial" -#: rhodecode/controllers/pullrequests.py:147 +#: kallithea/controllers/pullrequests.py:158 msgid "Peer branches" msgstr "Ramos pares" -#: rhodecode/controllers/pullrequests.py:148 rhodecode/model/scm.py:688 -#: rhodecode/templates/switch_to_list.html:28 -#: rhodecode/templates/bookmarks/bookmarks.html:10 +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 msgid "Bookmarks" msgstr "Marcadores" -#: rhodecode/controllers/pullrequests.py:321 +#: kallithea/controllers/pullrequests.py:330 msgid "Pull request requires a title with min. 3 chars" msgstr "O pull request requer um título com no mínimo três caracteres" -#: rhodecode/controllers/pullrequests.py:323 -msgid "Error creating pull request" -msgstr "Erro criando um pull request" - -#: rhodecode/controllers/pullrequests.py:343 +#: kallithea/controllers/pullrequests.py:332 +#, python-format +msgid "Error creating pull request: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:354 msgid "Successfully opened new pull request" msgstr "Novo pull request criado com sucesso" -#: rhodecode/controllers/pullrequests.py:346 +#: kallithea/controllers/pullrequests.py:357 msgid "Error occurred during sending pull request" msgstr "Ocorreu um erro durante o envio do pull request" -#: rhodecode/controllers/pullrequests.py:385 +#: kallithea/controllers/pullrequests.py:397 msgid "Successfully deleted pull request" msgstr "Pull request excluído com sucesso" -#: rhodecode/controllers/pullrequests.py:481 +#: kallithea/controllers/pullrequests.py:485 msgid "Closing with" msgstr "Fechando com" -#: rhodecode/controllers/pullrequests.py:518 -msgid "" -"Closing pull request on other statuses than rejected or approved forbidden" -msgstr "Não é permitido fechar um pull request em um estado diferente de rejeitado ou aprovado" - -#: rhodecode/controllers/search.py:132 +#: kallithea/controllers/pullrequests.py:522 +msgid "Closing pull request on other statuses than rejected or approved forbidden" +msgstr "" +"Não é permitido fechar um pull request em um estado diferente de " +"rejeitado ou aprovado" + +#: kallithea/controllers/search.py:135 msgid "Invalid search query. Try quoting it." msgstr "Consulta de busca inválida. Tente usar aspas." -#: rhodecode/controllers/search.py:137 +#: kallithea/controllers/search.py:140 msgid "There is no index to search in. Please run whoosh indexer" msgstr "Não há índice onde pesquisa. Por favor execute o indexador whoosh" -#: rhodecode/controllers/search.py:141 +#: kallithea/controllers/search.py:144 msgid "An error occurred during this search operation" msgstr "Ocorreu um erro durante essa operação de busca" -#: rhodecode/controllers/summary.py:182 +#: kallithea/controllers/summary.py:203 msgid "No data loaded yet" msgstr "Ainda não há dados carregados" -#: rhodecode/controllers/summary.py:188 -#: rhodecode/templates/summary/summary.html:149 +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 msgid "Statistics are disabled for this repository" msgstr "As estatísticas estão desabillitadas para este repositório" -#: rhodecode/controllers/admin/defaults.py:96 +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:97 msgid "Default settings updated successfully" msgstr "Configurações padrão atualizadas com sucesso" -#: rhodecode/controllers/admin/defaults.py:110 +#: kallithea/controllers/admin/defaults.py:111 msgid "Error occurred during update of defaults" msgstr "Ocorreu um erro durnge a atualização dos padrões" -#: rhodecode/controllers/admin/gists.py:56 +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 msgid "forever" msgstr "para sempre" -#: rhodecode/controllers/admin/gists.py:57 +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 msgid "5 minutes" msgstr "cinco minutos" -#: rhodecode/controllers/admin/gists.py:58 +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 msgid "1 hour" msgstr "uma hora" -#: rhodecode/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 msgid "1 day" msgstr "um dia" -#: rhodecode/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 msgid "1 month" msgstr "um mês" -#: rhodecode/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 msgid "Lifetime" msgstr "" -#: rhodecode/controllers/admin/gists.py:127 +#: kallithea/controllers/admin/gists.py:147 msgid "Error occurred during gist creation" msgstr "Ocorreu um erro durante a criação de um gist" -#: rhodecode/controllers/admin/gists.py:165 +#: kallithea/controllers/admin/gists.py:185 #, python-format msgid "Deleted gist %s" msgstr "Gist %s excluído" -#: rhodecode/controllers/admin/ldap_settings.py:50 -msgid "BASE" -msgstr "BASE" - -#: rhodecode/controllers/admin/ldap_settings.py:51 -msgid "ONELEVEL" -msgstr "UMNÍVEL" - -#: rhodecode/controllers/admin/ldap_settings.py:52 -msgid "SUBTREE" -msgstr "SUBÁRVORE" - -#: rhodecode/controllers/admin/ldap_settings.py:56 -msgid "NEVER" -msgstr "NUNCA" - -#: rhodecode/controllers/admin/ldap_settings.py:57 -msgid "ALLOW" -msgstr "PERMITIR" - -#: rhodecode/controllers/admin/ldap_settings.py:58 -msgid "TRY" -msgstr "TENTAR" - -#: rhodecode/controllers/admin/ldap_settings.py:59 -msgid "DEMAND" -msgstr "EXIGIR" - -#: rhodecode/controllers/admin/ldap_settings.py:60 -msgid "HARD" -msgstr "DIFÍCIL" - -#: rhodecode/controllers/admin/ldap_settings.py:64 -msgid "No encryption" -msgstr "Sem criptografia" - -#: rhodecode/controllers/admin/ldap_settings.py:65 -msgid "LDAPS connection" -msgstr "Conexão LDAPS" - -#: rhodecode/controllers/admin/ldap_settings.py:66 -msgid "START_TLS on LDAP connection" -msgstr "START_TLS na conexão LDAP" - -#: rhodecode/controllers/admin/ldap_settings.py:124 -msgid "LDAP settings updated successfully" -msgstr "Configurações de LDAP atualizadas com sucesso" - -#: rhodecode/controllers/admin/ldap_settings.py:128 -msgid "Unable to activate ldap. The \"python-ldap\" library is missing." -msgstr "Não foi possível ativar LDAP. A biblioteca \"python-ldap\" está faltando." - -#: rhodecode/controllers/admin/ldap_settings.py:145 -msgid "Error occurred during update of ldap settings" -msgstr "Ocorreu um erro durante a atualização das configurações de LDAP" - -#: rhodecode/controllers/admin/permissions.py:58 -#: rhodecode/controllers/admin/permissions.py:62 -#: rhodecode/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "Você não pode editar esse usuário pois ele é crucial para toda a aplicação" + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "Sua conta foi atualizada com sucesso" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "Ocorreu um erro durante a atualização do usuário %s" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "Email %s adicionado ao usuário" + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "Ocorreu um erro durante o salvamento do email" + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "Email removido do usuário" + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 msgid "None" msgstr "Nenhum" -#: rhodecode/controllers/admin/permissions.py:59 -#: rhodecode/controllers/admin/permissions.py:63 -#: rhodecode/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 msgid "Read" msgstr "Ler" -#: rhodecode/controllers/admin/permissions.py:60 -#: rhodecode/controllers/admin/permissions.py:64 -#: rhodecode/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 msgid "Write" msgstr "Gravar" -#: rhodecode/controllers/admin/permissions.py:61 -#: rhodecode/controllers/admin/permissions.py:65 -#: rhodecode/controllers/admin/permissions.py:69 -#: rhodecode/templates/admin/defaults/defaults.html:9 -#: rhodecode/templates/admin/ldap/ldap.html:9 -#: rhodecode/templates/admin/permissions/permissions.html:9 -#: rhodecode/templates/admin/repos/repo_add.html:10 -#: rhodecode/templates/admin/repos/repo_add.html:14 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:13 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:9 -#: rhodecode/templates/admin/users/user_add.html:8 -#: rhodecode/templates/admin/users/user_edit.html:9 -#: rhodecode/templates/admin/users/user_edit.html:133 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/admin/users/users.html:85 -#: rhodecode/templates/admin/users_groups/users_group_add.html:8 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 -#: rhodecode/templates/admin/users_groups/users_groups.html:9 -#: rhodecode/templates/base/base.html:317 -#: rhodecode/templates/base/base.html:318 -#: rhodecode/templates/base/base.html:324 -#: rhodecode/templates/base/base.html:325 +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 msgid "Admin" msgstr "Administrador" -#: rhodecode/controllers/admin/permissions.py:72 -#: rhodecode/controllers/admin/permissions.py:83 -#: rhodecode/controllers/admin/permissions.py:86 -#: rhodecode/controllers/admin/permissions.py:89 -#: rhodecode/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 msgid "Disabled" msgstr "Desabilitado" -#: rhodecode/controllers/admin/permissions.py:74 +#: kallithea/controllers/admin/permissions.py:78 msgid "Allowed with manual account activation" msgstr "Permitido com ativação manual de conta" -#: rhodecode/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:80 msgid "Allowed with automatic account activation" msgstr "Permitido com ativação automática de conta" -#: rhodecode/controllers/admin/permissions.py:79 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1439 rhodecode/model/db.py:1444 +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 msgid "Manual activation of external account" msgstr "Ativação manual de conta externa" -#: rhodecode/controllers/admin/permissions.py:80 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1440 rhodecode/model/db.py:1445 +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 msgid "Automatic activation of external account" msgstr "Ativação automática de conta externa" -#: rhodecode/controllers/admin/permissions.py:84 -#: rhodecode/controllers/admin/permissions.py:87 -#: rhodecode/controllers/admin/permissions.py:90 -#: rhodecode/controllers/admin/permissions.py:93 +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 msgid "Enabled" msgstr "Habilitado" -#: rhodecode/controllers/admin/permissions.py:138 -msgid "Default permissions updated successfully" -msgstr "Permissões padrões atualizadas com sucesso" - -#: rhodecode/controllers/admin/permissions.py:152 +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:139 msgid "Error occurred during update of permissions" msgstr "Ocorreu um erro durante a atualização das permissões" -#: rhodecode/controllers/admin/repos.py:128 -msgid "--REMOVE FORK--" -msgstr "--REMOVER BIFURCAÇÂO--" - -#: rhodecode/controllers/admin/repos.py:168 +#: kallithea/controllers/admin/repo_groups.py:186 +#, python-format +msgid "Created repository group %s" +msgstr "Grupo de repositórios %s criado" + +#: kallithea/controllers/admin/repo_groups.py:198 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "Ocorreu um erro durante a criação do grupo de repositórios %s" + +#: kallithea/controllers/admin/repo_groups.py:256 +#, python-format +msgid "Updated repository group %s" +msgstr "Grupo de repositórios %s atualizado" + +#: kallithea/controllers/admin/repo_groups.py:271 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "Ocorreu um erro durante a atualização do grupo de repositórios %s" + +#: kallithea/controllers/admin/repo_groups.py:289 +#, python-format +msgid "This group contains %s repositores and cannot be deleted" +msgstr "Esse grupo contém %s repositórios e não pode ser excluído" + +#: kallithea/controllers/admin/repo_groups.py:296 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "Este grupo contém %s subgrupos e não pode ser excluído" + +#: kallithea/controllers/admin/repo_groups.py:302 +#, python-format +msgid "Removed repository group %s" +msgstr "Grupo de repositórios %s excluído" + +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "Ocorreu um erro durante a exclusão do grupo de repositórios %s" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "Você não pode revocar sua própria permissão de administrador" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "Permissões atualizadas do Grupo de Repositórios" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "Ocorreu um erro durante a revocação das permissões" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "Erro ao criar repositório %s" + +#: kallithea/controllers/admin/repos.py:237 #, python-format msgid "Created repository %s from %s" msgstr "Repositório %s criado de %s" -#: rhodecode/controllers/admin/repos.py:174 +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "Repositório %s bifurcado como %s" + +#: kallithea/controllers/admin/repos.py:249 #, python-format msgid "Created repository %s" msgstr "Repositório %s criado" -#: rhodecode/controllers/admin/repos.py:197 -#, python-format -msgid "Error creating repository %s" -msgstr "Erro ao criar repositório %s" - -#: rhodecode/controllers/admin/repos.py:270 +#: kallithea/controllers/admin/repos.py:289 #, python-format msgid "Repository %s updated successfully" msgstr "Repositório %s atualizado com sucesso" -#: rhodecode/controllers/admin/repos.py:288 +#: kallithea/controllers/admin/repos.py:307 #, python-format msgid "Error occurred during update of repository %s" msgstr "Ocorreu um erro durante a atualização do repositório %s" -#: rhodecode/controllers/admin/repos.py:315 +#: kallithea/controllers/admin/repos.py:334 #, python-format msgid "Detached %s forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:318 +#: kallithea/controllers/admin/repos.py:337 #, python-format msgid "Deleted %s forks" msgstr "%s bifurcações excluídas" -#: rhodecode/controllers/admin/repos.py:323 +#: kallithea/controllers/admin/repos.py:342 #, python-format msgid "Deleted repository %s" msgstr "Repositório %s excluído" -#: rhodecode/controllers/admin/repos.py:326 +#: kallithea/controllers/admin/repos.py:345 #, python-format msgid "Cannot delete %s it still contains attached forks" msgstr "Nao é possível excluir %s pois ele ainda contém bifurcações vinculadas" -#: rhodecode/controllers/admin/repos.py:331 +#: kallithea/controllers/admin/repos.py:350 #, python-format msgid "An error occurred during deletion of %s" msgstr "Ocorreu um erro durante a exclusão de %s" -#: rhodecode/controllers/admin/repos.py:345 +#: kallithea/controllers/admin/repos.py:402 msgid "Repository permissions updated" msgstr "Permissões do repositório atualizadas" -#: rhodecode/controllers/admin/repos.py:375 -#: rhodecode/controllers/admin/repos_groups.py:332 -#: rhodecode/controllers/admin/users_groups.py:312 -msgid "An error occurred during revoking of permission" -msgstr "Ocorreu um erro durante a revocação das permissões" - -#: rhodecode/controllers/admin/repos.py:392 -msgid "An error occurred during deletion of repository stats" -msgstr "Ocorreu um erro ao excluir estatísticas de repositório" - -#: rhodecode/controllers/admin/repos.py:409 -msgid "An error occurred during cache invalidation" -msgstr "Ocorreu um erro ao invalidar o cache" - -#: rhodecode/controllers/admin/repos.py:429 -#: rhodecode/controllers/admin/repos.py:456 -msgid "An error occurred during unlocking" -msgstr "Ocorreu um erro durante o destravamento" - -#: rhodecode/controllers/admin/repos.py:447 -msgid "Unlocked" -msgstr "Destravado" - -#: rhodecode/controllers/admin/repos.py:450 -msgid "Locked" -msgstr "Travado" - -#: rhodecode/controllers/admin/repos.py:452 -#, python-format -msgid "Repository has been %s" -msgstr "O repositório foi %s" - -#: rhodecode/controllers/admin/repos.py:476 +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "Ocorreu um erro durante a criação do campo" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "Ocorreu um erro durante a remoção do campo" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "" + +#: kallithea/controllers/admin/repos.py:522 msgid "Updated repository visibility in public journal" msgstr "Atualizada a visibilidade do repositório no diário público" -#: rhodecode/controllers/admin/repos.py:480 +#: kallithea/controllers/admin/repos.py:526 msgid "An error occurred during setting this repository in public journal" msgstr "Ocorreu um erro ao ajustar esse repositório no diário público" -#: rhodecode/controllers/admin/repos.py:485 rhodecode/model/validators.py:302 +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 msgid "Token mismatch" msgstr "Descompasso de Token" -#: rhodecode/controllers/admin/repos.py:498 -msgid "Pulled from remote location" -msgstr "Realizado pull de localização remota" - -#: rhodecode/controllers/admin/repos.py:501 -msgid "An error occurred during pull from remote location" -msgstr "Ocorreu um erro ao realizar pull de localização remota" - -#: rhodecode/controllers/admin/repos.py:517 +#: kallithea/controllers/admin/repos.py:546 msgid "Nothing" msgstr "Nada" -#: rhodecode/controllers/admin/repos.py:519 +#: kallithea/controllers/admin/repos.py:548 #, python-format msgid "Marked repo %s as fork of %s" msgstr "Marcado repositório %s como bifurcação de %s" -#: rhodecode/controllers/admin/repos.py:523 +#: kallithea/controllers/admin/repos.py:555 msgid "An error occurred during this operation" msgstr "Ocorreu um erro durante essa operação" -#: rhodecode/controllers/admin/repos.py:562 -msgid "An error occurred during creation of field" -msgstr "Ocorreu um erro durante a criação do campo" - -#: rhodecode/controllers/admin/repos.py:576 -msgid "An error occurred during removal of field" -msgstr "Ocorreu um erro durante a remoção do campo" - -#: rhodecode/controllers/admin/repos_groups.py:147 -#, python-format -msgid "Created repository group %s" -msgstr "Grupo de repositórios %s criado" - -#: rhodecode/controllers/admin/repos_groups.py:159 -#, python-format -msgid "Error occurred during creation of repository group %s" -msgstr "Ocorreu um erro durante a criação do grupo de repositórios %s" - -#: rhodecode/controllers/admin/repos_groups.py:217 -#, python-format -msgid "Updated repository group %s" -msgstr "Grupo de repositórios %s atualizado" - -#: rhodecode/controllers/admin/repos_groups.py:232 -#, python-format -msgid "Error occurred during update of repository group %s" -msgstr "Ocorreu um erro durante a atualização do grupo de repositórios %s" - -#: rhodecode/controllers/admin/repos_groups.py:250 -#, python-format -msgid "This group contains %s repositores and cannot be deleted" -msgstr "Esse grupo contém %s repositórios e não pode ser excluído" - -#: rhodecode/controllers/admin/repos_groups.py:257 -#, python-format -msgid "This group contains %s subgroups and cannot be deleted" -msgstr "Este grupo contém %s subgrupos e não pode ser excluído" - -#: rhodecode/controllers/admin/repos_groups.py:263 -#, python-format -msgid "Removed repository group %s" -msgstr "Grupo de repositórios %s excluído" - -#: rhodecode/controllers/admin/repos_groups.py:268 -#, python-format -msgid "Error occurred during deletion of repository group %s" -msgstr "Ocorreu um erro durante a exclusão do grupo de repositórios %s" - -#: rhodecode/controllers/admin/repos_groups.py:279 -#: rhodecode/controllers/admin/repos_groups.py:314 -#: rhodecode/controllers/admin/users_groups.py:300 -msgid "Cannot revoke permission for yourself as admin" -msgstr "Você não pode revocar sua própria permissão de administrador" - -#: rhodecode/controllers/admin/repos_groups.py:294 -msgid "Repository Group permissions updated" -msgstr "Permissões atualizadas do Grupo de Repositórios" - -#: rhodecode/controllers/admin/settings.py:123 +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 +msgid "An error occurred during unlocking" +msgstr "Ocorreu um erro durante o destravamento" + +#: kallithea/controllers/admin/repos.py:595 +msgid "Unlocked" +msgstr "Destravado" + +#: kallithea/controllers/admin/repos.py:598 +msgid "Locked" +msgstr "Travado" + +#: kallithea/controllers/admin/repos.py:600 +#, python-format +msgid "Repository has been %s" +msgstr "O repositório foi %s" + +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "Ocorreu um erro ao invalidar o cache" + +#: kallithea/controllers/admin/repos.py:637 +msgid "Pulled from remote location" +msgstr "Realizado pull de localização remota" + +#: kallithea/controllers/admin/repos.py:640 +msgid "An error occurred during pull from remote location" +msgstr "Ocorreu um erro ao realizar pull de localização remota" + +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "Ocorreu um erro ao excluir estatísticas de repositório" + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "Configurações de VCS atualizadas" + +#: kallithea/controllers/admin/settings.py:176 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "Ocorreu um erro durante a atualização das configurações da aplicação" + +#: kallithea/controllers/admin/settings.py:215 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" msgstr "Repositórios varridos com sucesso adicionados: %s ; removidos: %s" -#: rhodecode/controllers/admin/settings.py:132 -msgid "Whoosh reindex task scheduled" -msgstr "Tarefa de reindexação do whoosh agendada" - -#: rhodecode/controllers/admin/settings.py:163 +#: kallithea/controllers/admin/settings.py:270 msgid "Updated application settings" msgstr "Configurações da aplicação atualizadas" -#: rhodecode/controllers/admin/settings.py:167 -#: rhodecode/controllers/admin/settings.py:304 -msgid "Error occurred during updating application settings" -msgstr "Ocorreu um erro durante a atualização das configurações da aplicação" - -#: rhodecode/controllers/admin/settings.py:219 +#: kallithea/controllers/admin/settings.py:327 msgid "Updated visualisation settings" msgstr "Configurações de visualização atualizadas" -#: rhodecode/controllers/admin/settings.py:224 +#: kallithea/controllers/admin/settings.py:332 msgid "Error occurred during updating visualisation settings" msgstr "Ocorreu um erro durante a atualização das configurações de visualização" -#: rhodecode/controllers/admin/settings.py:300 -msgid "Updated VCS settings" -msgstr "Configurações de VCS atualizadas" - -#: rhodecode/controllers/admin/settings.py:314 +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "" + +#: kallithea/controllers/admin/settings.py:400 msgid "Added new hook" msgstr "Adicionado novo gancho" -#: rhodecode/controllers/admin/settings.py:326 +#: kallithea/controllers/admin/settings.py:414 msgid "Updated hooks" msgstr "Atualizados os ganchos" -#: rhodecode/controllers/admin/settings.py:330 +#: kallithea/controllers/admin/settings.py:418 msgid "Error occurred during hook creation" msgstr "Ocorreu um erro durante a criação do hook" -#: rhodecode/controllers/admin/settings.py:349 -msgid "Email task created" -msgstr "Tarefa de e-mail criada" - -#: rhodecode/controllers/admin/settings.py:413 -msgid "You can't edit this user since it's crucial for entire application" -msgstr "Você não pode editar esse usuário pois ele é crucial para toda a aplicação" - -#: rhodecode/controllers/admin/settings.py:455 -msgid "Your account was updated successfully" -msgstr "Sua conta foi atualizada com sucesso" - -#: rhodecode/controllers/admin/settings.py:470 -#: rhodecode/controllers/admin/users.py:198 -#, python-format -msgid "Error occurred during update of user %s" -msgstr "Ocorreu um erro durante a atualização do usuário %s" - -#: rhodecode/controllers/admin/users.py:130 +#: kallithea/controllers/admin/settings.py:444 +msgid "Whoosh reindex task scheduled" +msgstr "Tarefa de reindexação do whoosh agendada" + +#: kallithea/controllers/admin/user_groups.py:150 +#, python-format +msgid "Created user group %s" +msgstr "Grupo de usuários %s criado" + +#: kallithea/controllers/admin/user_groups.py:161 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "Ocorreu um erro durante a criação do grupo de usuários %s" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Updated user group %s" +msgstr "Grupo de usuários %s atualizado" + +#: kallithea/controllers/admin/user_groups.py:221 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "Ocorreu um erro durante a atualização do grupo de usuários %s" + +#: kallithea/controllers/admin/user_groups.py:239 +msgid "Successfully deleted user group" +msgstr "Grupo de usuários excluído com sucesso" + +#: kallithea/controllers/admin/user_groups.py:244 +msgid "An error occurred during deletion of user group" +msgstr "Ocorreu um erro durante a exclusão do grupo de usuários" + +#: kallithea/controllers/admin/user_groups.py:311 +msgid "Target group cannot be the same" +msgstr "O grupo destino não pode ser o mesmo" + +#: kallithea/controllers/admin/user_groups.py:317 +msgid "User Group permissions updated" +msgstr "Permissões do Grupo de Usuários atualizadas" + +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "Permissões atualizadas" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "Ocorreu um erro durante o salvamento das permissões" + +#: kallithea/controllers/admin/users.py:135 #, python-format msgid "Created user %s" msgstr "Usuário %s criado" -#: rhodecode/controllers/admin/users.py:142 +#: kallithea/controllers/admin/users.py:149 #, python-format msgid "Error occurred during creation of user %s" msgstr "Ocorreu um erro durante a criação do usuário %s" -#: rhodecode/controllers/admin/users.py:176 +#: kallithea/controllers/admin/users.py:188 msgid "User updated successfully" msgstr "Usuário atualizado com sucesso" -#: rhodecode/controllers/admin/users.py:214 +#: kallithea/controllers/admin/users.py:223 msgid "Successfully deleted user" msgstr "Usuário excluído com sucesso" -#: rhodecode/controllers/admin/users.py:219 +#: kallithea/controllers/admin/users.py:228 msgid "An error occurred during deletion of user" msgstr "Ocorreu um erro ao excluir o usuário" -#: rhodecode/controllers/admin/users.py:234 +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 msgid "You can't edit this user" msgstr "Você não pode editar esse usuário" -#: rhodecode/controllers/admin/users.py:293 -#: rhodecode/controllers/admin/users_groups.py:372 -msgid "Updated permissions" -msgstr "Permissões atualizadas" - -#: rhodecode/controllers/admin/users.py:297 -#: rhodecode/controllers/admin/users_groups.py:376 -msgid "An error occurred during permissions saving" -msgstr "Ocorreu um erro durante o salvamento das permissões" - -#: rhodecode/controllers/admin/users.py:311 -#, python-format -msgid "Added email %s to user" -msgstr "Email %s adicionado ao usuário" - -#: rhodecode/controllers/admin/users.py:317 -msgid "An error occurred during email saving" -msgstr "Ocorreu um erro durante o salvamento do email" - -#: rhodecode/controllers/admin/users.py:327 -msgid "Removed email from user" -msgstr "Email removido do usuário" - -#: rhodecode/controllers/admin/users.py:340 -#, python-format -msgid "Added ip %s to user" -msgstr "IP %s adicionado ao usuário" - -#: rhodecode/controllers/admin/users.py:346 +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "" + +#: kallithea/controllers/admin/users.py:489 msgid "An error occurred during ip saving" msgstr "Ocorreu um erro durante o salvamento do IP" -#: rhodecode/controllers/admin/users.py:358 -msgid "Removed ip from user" -msgstr "IP removido do usuário" - -#: rhodecode/controllers/admin/users_groups.py:162 -#, python-format -msgid "Created user group %s" -msgstr "Grupo de usuários %s criado" - -#: rhodecode/controllers/admin/users_groups.py:173 -#, python-format -msgid "Error occurred during creation of user group %s" -msgstr "Ocorreu um erro durante a criação do grupo de usuários %s" - -#: rhodecode/controllers/admin/users_groups.py:210 -#, python-format -msgid "Updated user group %s" -msgstr "Grupo de usuários %s atualizado" - -#: rhodecode/controllers/admin/users_groups.py:232 -#, python-format -msgid "Error occurred during update of user group %s" -msgstr "Ocorreu um erro durante a atualização do grupo de usuários %s" - -#: rhodecode/controllers/admin/users_groups.py:250 -msgid "Successfully deleted user group" -msgstr "Grupo de usuários excluído com sucesso" - -#: rhodecode/controllers/admin/users_groups.py:255 -msgid "An error occurred during deletion of user group" -msgstr "Ocorreu um erro durante a exclusão do grupo de usuários" - -#: rhodecode/controllers/admin/users_groups.py:274 -msgid "Target group cannot be the same" -msgstr "O grupo destino não pode ser o mesmo" - -#: rhodecode/controllers/admin/users_groups.py:280 -msgid "User Group permissions updated" -msgstr "Permissões do Grupo de Usuários atualizadas" - -#: rhodecode/lib/auth.py:544 +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "" + +#: kallithea/lib/auth.py:748 #, python-format msgid "IP %s not allowed" msgstr "IP %s não permitido" -#: rhodecode/lib/auth.py:593 +#: kallithea/lib/auth.py:809 msgid "You need to be a registered user to perform this action" msgstr "Você precisa ser um usuário registrado para realizar essa ação" -#: rhodecode/lib/auth.py:634 +#: kallithea/lib/auth.py:846 msgid "You need to be a signed in to view this page" msgstr "Você precisa estar logado para ver essa página" -#: rhodecode/lib/diffs.py:66 +#: kallithea/lib/diffs.py:66 msgid "Binary file" msgstr "Arquivo binário" -#: rhodecode/lib/diffs.py:82 -msgid "" -"Changeset was too big and was cut off, use diff menu to display this diff" -msgstr "Conjunto de mudanças é grande demais e foi cortado, use o menu de diferenças para ver as diferenças" - -#: rhodecode/lib/diffs.py:92 +#: kallithea/lib/diffs.py:82 +msgid "Changeset was too big and was cut off, use diff menu to display this diff" +msgstr "" +"Conjunto de mudanças é grande demais e foi cortado, use o menu de " +"diferenças para ver as diferenças" + +#: kallithea/lib/diffs.py:92 msgid "No changes detected" msgstr "Nenhuma alteração detectada" -#: rhodecode/lib/helpers.py:539 -msgid "True" -msgstr "Verdadeiro" - -#: rhodecode/lib/helpers.py:542 -msgid "False" -msgstr "Falso" - -#: rhodecode/lib/helpers.py:580 +#: kallithea/lib/helpers.py:598 #, python-format msgid "Deleted branch: %s" msgstr "Excluído ramo: %s" -#: rhodecode/lib/helpers.py:583 +#: kallithea/lib/helpers.py:601 #, python-format msgid "Created tag: %s" msgstr "Tag criada: %s" -#: rhodecode/lib/helpers.py:596 +#: kallithea/lib/helpers.py:614 msgid "Changeset not found" msgstr "Conjunto de alterações não encontrado" -#: rhodecode/lib/helpers.py:646 +#: kallithea/lib/helpers.py:664 #, python-format msgid "Show all combined changesets %s->%s" msgstr "Ver todos os conjuntos de mudanças combinados %s->%s" -#: rhodecode/lib/helpers.py:652 +#: kallithea/lib/helpers.py:670 msgid "compare view" msgstr "comparar exibir" -#: rhodecode/lib/helpers.py:672 +#: kallithea/lib/helpers.py:690 msgid "and" msgstr "e" -#: rhodecode/lib/helpers.py:673 +#: kallithea/lib/helpers.py:691 #, python-format msgid "%s more" msgstr "%s mais" -#: rhodecode/lib/helpers.py:674 -#: rhodecode/templates/changelog/changelog.html:53 +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 msgid "revisions" msgstr "revisões" -#: rhodecode/lib/helpers.py:698 +#: kallithea/lib/helpers.py:716 #, python-format msgid "fork name %s" -msgstr "" - -#: rhodecode/lib/helpers.py:715 -#: rhodecode/templates/pullrequests/pullrequest_show.html:8 +msgstr "nome da bifurcação %s" + +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 #, python-format msgid "Pull request #%s" msgstr "Pull request #%s" -#: rhodecode/lib/helpers.py:725 +#: kallithea/lib/helpers.py:743 msgid "[deleted] repository" msgstr "repositório [excluído]" -#: rhodecode/lib/helpers.py:727 rhodecode/lib/helpers.py:739 +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 msgid "[created] repository" msgstr "repositório [criado]" -#: rhodecode/lib/helpers.py:729 +#: kallithea/lib/helpers.py:747 msgid "[created] repository as fork" msgstr "repositório [criado] como uma bifurcação" -#: rhodecode/lib/helpers.py:731 rhodecode/lib/helpers.py:741 +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 msgid "[forked] repository" msgstr "repositório [bifurcado]" -#: rhodecode/lib/helpers.py:733 rhodecode/lib/helpers.py:743 +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 msgid "[updated] repository" msgstr "repositório [atualizado]" -#: rhodecode/lib/helpers.py:735 +#: kallithea/lib/helpers.py:753 msgid "[downloaded] archive from repository" msgstr "[baixado] archive do repositório" -#: rhodecode/lib/helpers.py:737 +#: kallithea/lib/helpers.py:755 msgid "[delete] repository" msgstr "[excluir] repositório" -#: rhodecode/lib/helpers.py:745 +#: kallithea/lib/helpers.py:763 msgid "[created] user" msgstr "usuário [criado]" -#: rhodecode/lib/helpers.py:747 +#: kallithea/lib/helpers.py:765 msgid "[updated] user" msgstr "usuário [atualizado]" -#: rhodecode/lib/helpers.py:749 +#: kallithea/lib/helpers.py:767 msgid "[created] user group" msgstr "[criado] grupo de usuários" -#: rhodecode/lib/helpers.py:751 +#: kallithea/lib/helpers.py:769 msgid "[updated] user group" msgstr "[atualizado] grupo de usuários" -#: rhodecode/lib/helpers.py:753 +#: kallithea/lib/helpers.py:771 msgid "[commented] on revision in repository" msgstr "[comentado] em revisão no repositório" -#: rhodecode/lib/helpers.py:755 +#: kallithea/lib/helpers.py:773 msgid "[commented] on pull request for" msgstr "[comentado] no pull request para" -#: rhodecode/lib/helpers.py:757 +#: kallithea/lib/helpers.py:775 msgid "[closed] pull request for" msgstr "[fechado] pull request para" -#: rhodecode/lib/helpers.py:759 +#: kallithea/lib/helpers.py:777 msgid "[pushed] into" msgstr "[realizado push] para" -#: rhodecode/lib/helpers.py:761 -msgid "[committed via RhodeCode] into repository" -msgstr "[commitado via RhodeCode] no repositório" - -#: rhodecode/lib/helpers.py:763 +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "[commitado via Kallithea] no repositório" + +#: kallithea/lib/helpers.py:781 msgid "[pulled from remote] into repository" msgstr "[pulled do remote] no repositório" -#: rhodecode/lib/helpers.py:765 +#: kallithea/lib/helpers.py:783 msgid "[pulled] from" msgstr "[realizado pull] a partir de" -#: rhodecode/lib/helpers.py:767 +#: kallithea/lib/helpers.py:785 msgid "[started following] repository" msgstr "[passou a seguir] o repositório" -#: rhodecode/lib/helpers.py:769 +#: kallithea/lib/helpers.py:787 msgid "[stopped following] repository" msgstr "[parou de seguir] o repositório" -#: rhodecode/lib/helpers.py:1088 +#: kallithea/lib/helpers.py:1101 #, python-format msgid " and %s more" msgstr " e mais %s" -#: rhodecode/lib/helpers.py:1092 +#: kallithea/lib/helpers.py:1105 msgid "No Files" msgstr "Nenhum Arquivo" -#: rhodecode/lib/helpers.py:1158 +#: kallithea/lib/helpers.py:1171 msgid "new file" msgstr "novo arquivo" -#: rhodecode/lib/helpers.py:1161 +#: kallithea/lib/helpers.py:1174 msgid "mod" msgstr "mod" -#: rhodecode/lib/helpers.py:1164 +#: kallithea/lib/helpers.py:1177 msgid "del" msgstr "excluir" -#: rhodecode/lib/helpers.py:1167 +#: kallithea/lib/helpers.py:1180 msgid "rename" msgstr "renomear" -#: rhodecode/lib/helpers.py:1172 +#: kallithea/lib/helpers.py:1185 msgid "chmod" msgstr "chmod" -#: rhodecode/lib/helpers.py:1404 +#: kallithea/lib/helpers.py:1417 #, python-format msgid "" -"%s repository is not mapped to db perhaps it was created or renamed from the" -" filesystem please run the application again in order to rescan repositories" -msgstr "O repositório %s não está mapeado ao BD. Talvez ele tenha sido criado ou renomeado a partir do sistema de arquivos. Por favor, execute a aplicação outra vez para varrer novamente por repositórios" - -#: rhodecode/lib/unionrepo.py:193 -msgid "cannot create new union repository" -msgstr "não é possível criar novo repositório de união" - -#: rhodecode/lib/utils2.py:410 +"%s repository is not mapped to db perhaps it was created or renamed from " +"the filesystem please run the application again in order to rescan " +"repositories" +msgstr "" +"O repositório %s não está mapeado ao BD. Talvez ele tenha sido criado ou " +"renomeado a partir do sistema de arquivos. Por favor, execute a aplicação" +" outra vez para varrer novamente por repositórios" + +#: kallithea/lib/utils2.py:415 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d ano" msgstr[1] "%d anos" -#: rhodecode/lib/utils2.py:411 +#: kallithea/lib/utils2.py:416 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d mês" msgstr[1] "%d meses" -#: rhodecode/lib/utils2.py:412 +#: kallithea/lib/utils2.py:417 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dia" msgstr[1] "%d dias" -#: rhodecode/lib/utils2.py:413 +#: kallithea/lib/utils2.py:418 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hora" msgstr[1] "%d horas" -#: rhodecode/lib/utils2.py:414 +#: kallithea/lib/utils2.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minutos" -#: rhodecode/lib/utils2.py:415 +#: kallithea/lib/utils2.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" -#: rhodecode/lib/utils2.py:431 +#: kallithea/lib/utils2.py:436 #, python-format msgid "in %s" msgstr "em %s" -#: rhodecode/lib/utils2.py:433 +#: kallithea/lib/utils2.py:438 #, python-format msgid "%s ago" msgstr "%s atrás" -#: rhodecode/lib/utils2.py:435 +#: kallithea/lib/utils2.py:440 #, python-format msgid "in %s and %s" msgstr "em %s e %s" -#: rhodecode/lib/utils2.py:438 +#: kallithea/lib/utils2.py:443 #, python-format msgid "%s and %s ago" msgstr "%s e %s atrás" -#: rhodecode/lib/utils2.py:441 +#: kallithea/lib/utils2.py:446 msgid "just now" msgstr "agora há pouco" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1163 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1303 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1388 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1408 rhodecode/model/db.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 msgid "Repository no access" msgstr "Nenhum acesso ao repositório" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1164 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1184 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1304 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1389 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1409 rhodecode/model/db.py:1414 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 msgid "Repository read access" msgstr "Acesso de leitura ao repositório" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1165 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1185 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1305 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1390 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1410 rhodecode/model/db.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 msgid "Repository write access" msgstr "Acesso de escrita ao repositório" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1166 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1186 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1306 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1391 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1411 rhodecode/model/db.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 msgid "Repository admin access" msgstr "Acesso administrativo ao repositório" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1168 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 msgid "Repositories Group no access" msgstr "Nenhum acesso ao Grupo de Repositórios" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1169 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1309 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 msgid "Repositories Group read access" msgstr "Acesso de leitura ao Grupo de Repositórios" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1170 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1310 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 msgid "Repositories Group write access" msgstr "Acesso de escrita ao Grupo de Repositórios" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1171 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1311 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 msgid "Repositories Group admin access" msgstr "Acesso administrativo ao Grupo de Repositórios" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1173 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1193 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1313 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1398 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1406 rhodecode/model/db.py:1411 -msgid "RhodeCode Administrator" -msgstr "Administrador do RhodeCode" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1174 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1194 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1314 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1399 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1429 rhodecode/model/db.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" +msgstr "Administrador do Kallithea" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 msgid "Repository creation disabled" msgstr "Criação de repositórios desabilitada" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1175 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1195 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1315 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1400 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1430 rhodecode/model/db.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 msgid "Repository creation enabled" msgstr "Criação de repositórios habilitada" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1176 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1196 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1316 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1401 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1432 rhodecode/model/db.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 msgid "Repository forking disabled" msgstr "Bifurcação de repositórios desabilitada" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1177 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1197 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1317 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1402 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1433 rhodecode/model/db.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 msgid "Repository forking enabled" msgstr "Bifurcação de repositórios habilitada" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1178 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1318 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 msgid "Register disabled" msgstr "Registro desabilitado" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1319 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1404 -msgid "Register new user with RhodeCode with manual activation" -msgstr "Registro de novo usuário no RhodeCode com ativação manual" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1202 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1407 -msgid "Register new user with RhodeCode with auto activation" -msgstr "Registro de novo usuário no RhodeCode com auto-ativação" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1623 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1643 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1763 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1838 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1934 rhodecode/model/db.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" +msgstr "Registro de novo usuário no Kallithea com ativação manual" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" +msgstr "Registro de novo usuário no Kallithea com auto-ativação" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 msgid "Not Reviewed" msgstr "Não Revisado" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1624 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1644 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1764 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1839 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1935 rhodecode/model/db.py:1940 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 msgid "Approved" msgstr "Aprovado" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1625 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1645 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1765 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1840 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1936 rhodecode/model/db.py:1941 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 msgid "Rejected" msgstr "Rejeitado" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1626 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1646 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1766 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1841 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1937 rhodecode/model/db.py:1942 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 msgid "Under Review" msgstr "Sob Revisão" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1252 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1270 rhodecode/model/db.py:1275 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 msgid "top level" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1393 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1413 rhodecode/model/db.py:1418 +msgstr "nível superior" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 msgid "Repository group no access" msgstr "Sem acesso ao grupo de repositórios" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1394 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1414 rhodecode/model/db.py:1419 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 msgid "Repository group read access" msgstr "Acesso de leitura ao grupo de repositórios" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1395 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1415 rhodecode/model/db.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 msgid "Repository group write access" msgstr "Acesso de escrita ao grupo de repositórios" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1396 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1416 rhodecode/model/db.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 msgid "Repository group admin access" msgstr "Acesso administrativo ao grupo de repositórios" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1418 rhodecode/model/db.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 msgid "User group no access" msgstr "Sem acesso ao grupo de usuários" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1419 rhodecode/model/db.py:1424 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 msgid "User group read access" msgstr "Acesso de leitura ao grupo de usuários" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1420 rhodecode/model/db.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 msgid "User group write access" msgstr "Acesso de escrita ao grupo de usuários" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1421 rhodecode/model/db.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 msgid "User group admin access" msgstr "Acesso administrativo ao grupo de usuários" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1423 rhodecode/model/db.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 msgid "Repository Group creation disabled" msgstr "Criação de Grupo de Repositórios desatilibada" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1424 rhodecode/model/db.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 msgid "Repository Group creation enabled" msgstr "Criação de Grupo de Repositórios habilitada" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1426 rhodecode/model/db.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 msgid "User Group creation disabled" msgstr "Criação de Grupo de Usuários desabilitada" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1427 rhodecode/model/db.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 msgid "User Group creation enabled" msgstr "Criação de Grupo de Usuários habilitada" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1435 rhodecode/model/db.py:1440 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 msgid "Registration disabled" msgstr "Registro desatilitado" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1436 rhodecode/model/db.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 msgid "User Registration with manual account activation" msgstr "Registro de Usuário com ativação manual de conta" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1437 rhodecode/model/db.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 msgid "User Registration with automatic account activation" msgstr "Registro de Usuário com ativação automática de conta" -#: rhodecode/model/comment.py:75 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:77 #, python-format msgid "on line %s" msgstr "na linha %s" -#: rhodecode/model/comment.py:220 +#: kallithea/model/comment.py:222 msgid "[Mention]" msgstr "[Menção]" -#: rhodecode/model/forms.py:43 +#: kallithea/model/forms.py:57 msgid "Please enter a login" msgstr "Por favor entre um login" -#: rhodecode/model/forms.py:44 +#: kallithea/model/forms.py:58 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "Entre um valor com %(min)i caracteres ou mais" -#: rhodecode/model/forms.py:52 +#: kallithea/model/forms.py:66 msgid "Please enter a password" msgstr "Por favor entre com uma senha" -#: rhodecode/model/forms.py:53 +#: kallithea/model/forms.py:67 #, python-format msgid "Enter %(min)i characters or more" msgstr "Entre com %(min)i caracteres ou mais" -#: rhodecode/model/notification.py:228 +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:231 #, python-format msgid "%(user)s commented on changeset at %(when)s" msgstr "%(user)s comentou no changeset em %(when)s" -#: rhodecode/model/notification.py:229 +#: kallithea/model/notification.py:232 #, python-format msgid "%(user)s sent message at %(when)s" msgstr "%(user)s enviou mensagem em %(when)s" -#: rhodecode/model/notification.py:230 +#: kallithea/model/notification.py:233 #, python-format msgid "%(user)s mentioned you at %(when)s" msgstr "%(user)s mencionou-o em %(when)s" -#: rhodecode/model/notification.py:231 -#, python-format -msgid "%(user)s registered in RhodeCode at %(when)s" -msgstr "%(user)s registrou-se no RhodeCode em %(when)s" - -#: rhodecode/model/notification.py:232 +#: kallithea/model/notification.py:234 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "%(user)s registrou-se no Kallithea em %(when)s" + +#: kallithea/model/notification.py:235 #, python-format msgid "%(user)s opened new pull request at %(when)s" msgstr "%(user)s abriu um novo pull request em %(when)s" -#: rhodecode/model/notification.py:233 +#: kallithea/model/notification.py:236 #, python-format msgid "%(user)s commented on pull request at %(when)s" msgstr "%(user)s comentou no pull request em %(when)s" -#: rhodecode/model/pull_request.py:98 +#: kallithea/model/pull_request.py:107 #, python-format msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" msgstr "%(user)s solicita sua revisão no pull request $%(pr_id)s: %(pr_title)s" -#: rhodecode/model/scm.py:674 +#: kallithea/model/scm.py:810 msgid "latest tip" msgstr "tip mais recente" -#: rhodecode/model/user.py:232 +#: kallithea/model/user.py:198 msgid "New user registration" msgstr "Novo registro de usuário" -#: rhodecode/model/user.py:257 rhodecode/model/user.py:281 +#: kallithea/model/user.py:222 kallithea/model/user.py:247 msgid "You can't Edit this user since it's crucial for entire application" -msgstr "Você não pode Editar esse usuário, pois ele é crucial para toda a aplicação" - -#: rhodecode/model/user.py:303 +msgstr "" +"Você não pode Editar esse usuário, pois ele é crucial para toda a " +"aplicação" + +#: kallithea/model/user.py:270 msgid "You can't remove this user since it's crucial for entire application" -msgstr "Você não pode remover esse usuário, pois ele é crucial para toda a aplicação" - -#: rhodecode/model/user.py:309 +msgstr "" +"Você não pode remover esse usuário, pois ele é crucial para toda a " +"aplicação" + +#: kallithea/model/user.py:276 #, python-format msgid "" -"user \"%s\" still owns %s repositories and cannot be removed. Switch owners " -"or remove those repositories. %s" -msgstr "usuário \"%s\" ainda é dono de %s repositórios e não pode ser removido. Troque os donos ou remova esses repositórios. %s" - -#: rhodecode/model/user.py:334 +"user \"%s\" still owns %s repositories and cannot be removed. Switch " +"owners or remove those repositories. %s" +msgstr "" +"usuário \"%s\" ainda é dono de %s repositórios e não pode ser removido. " +"Troque os donos ou remova esses repositórios. %s" + +#: kallithea/model/user.py:304 msgid "Password reset link" msgstr "Link para trocar senha" -#: rhodecode/model/user.py:366 +#: kallithea/model/user.py:333 msgid "Your new password" msgstr "Sua nova senha" -#: rhodecode/model/user.py:367 -#, python-format -msgid "Your new RhodeCode password:%s" -msgstr "Sua nova senha no RhodeCode: %s" - -#: rhodecode/model/validators.py:38 rhodecode/model/validators.py:39 +#: kallithea/model/user.py:334 +#, python-format +msgid "Your new Kallithea password:%s" +msgstr "Sua nova senha no Kallithea: %s" + +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 msgid "Value cannot be an empty list" msgstr "O valor não pode ser uma lista vazia" -#: rhodecode/model/validators.py:85 +#: kallithea/model/validators.py:120 #, python-format msgid "Username \"%(username)s\" already exists" msgstr "O username \\\"%(username)s\\\" já existe" -#: rhodecode/model/validators.py:87 +#: kallithea/model/validators.py:122 #, python-format msgid "Username \"%(username)s\" is forbidden" msgstr "O username \\\"%(username)s\\\" é proibido" -#: rhodecode/model/validators.py:89 +#: kallithea/model/validators.py:124 msgid "" -"Username may only contain alphanumeric characters underscores, periods or " -"dashes and must begin with alphanumeric character or underscore" -msgstr "Nome de usuário pode conter somente caracteres alfanuméricos, sublinha, pontos e hífens e deve iniciar com caractere alfanumérico" - -#: rhodecode/model/validators.py:117 +"Username may only contain alphanumeric characters underscores, periods or" +" dashes and must begin with alphanumeric character or underscore" +msgstr "" +"Nome de usuário pode conter somente caracteres alfanuméricos, sublinha, " +"pontos e hífens e deve iniciar com caractere alfanumérico" + +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:158 #, python-format msgid "Username %(username)s is not valid" msgstr "O username \"%(username)s\" não é válido" -#: rhodecode/model/validators.py:136 +#: kallithea/model/validators.py:177 msgid "Invalid user group name" msgstr "Nome inválido de grupo de usuários" -#: rhodecode/model/validators.py:137 +#: kallithea/model/validators.py:178 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "O grupo de usuários \"%(usergroup)s\" já existe" -#: rhodecode/model/validators.py:139 +#: kallithea/model/validators.py:180 msgid "" "user group name may only contain alphanumeric characters underscores, " "periods or dashes and must begin with alphanumeric character" -msgstr "O nome de um grupo de usuários só pode conter characters alfa-numéricos, underscores, pontos ou hífens, e deve começar om um caractere alfa-numérico" - -#: rhodecode/model/validators.py:177 +msgstr "" +"O nome de um grupo de usuários só pode conter characters alfa-numéricos, " +"underscores, pontos ou hífens, e deve começar om um caractere alfa-" +"numérico" + +#: kallithea/model/validators.py:218 msgid "Cannot assign this group as parent" msgstr "Não é possível associar esse grupo como progenitor" -#: rhodecode/model/validators.py:178 +#: kallithea/model/validators.py:219 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "O grupo \\\"%(group_name)s\\\" já existe" -#: rhodecode/model/validators.py:180 +#: kallithea/model/validators.py:221 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "Um repositório com o nome \"%(group_name)s\" já existe" -#: rhodecode/model/validators.py:238 +#: kallithea/model/validators.py:279 msgid "Invalid characters (non-ascii) in password" msgstr "Caracteres inválidos (não-ascii) na senha" -#: rhodecode/model/validators.py:253 +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 msgid "Passwords do not match" msgstr "Senhas não conferem" -#: rhodecode/model/validators.py:270 +#: kallithea/model/validators.py:327 msgid "invalid password" msgstr "senha inválida" -#: rhodecode/model/validators.py:271 +#: kallithea/model/validators.py:328 msgid "invalid user name" msgstr "nome de usuário inválido" -#: rhodecode/model/validators.py:272 +#: kallithea/model/validators.py:329 msgid "Your account is disabled" msgstr "Sua conta está desabilitada" -#: rhodecode/model/validators.py:316 +#: kallithea/model/validators.py:373 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "O nome de repositório %(repo)s não é permitido" -#: rhodecode/model/validators.py:318 +#: kallithea/model/validators.py:375 #, python-format msgid "Repository named %(repo)s already exists" msgstr "Um repositório chamado %(repo)s já existe" -#: rhodecode/model/validators.py:319 +#: kallithea/model/validators.py:376 #, python-format msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" msgstr "Um repositório \"%(repo)s\" já existe no grupo \"%(group)s\"" -#: rhodecode/model/validators.py:321 +#: kallithea/model/validators.py:378 #, python-format msgid "Repository group with name \"%(repo)s\" already exists" msgstr "Um Grupo de Repositórios chamado \"%(repo)s\" já existe" -#: rhodecode/model/validators.py:438 +#: kallithea/model/validators.py:493 msgid "invalid clone url" msgstr "URL de clonagem inválida" -#: rhodecode/model/validators.py:439 +#: kallithea/model/validators.py:494 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" msgstr "URL inválida, por favor, forneça uma URL de clone http(s)/svn+http(s)" -#: rhodecode/model/validators.py:464 +#: kallithea/model/validators.py:519 msgid "Fork have to be the same type as parent" msgstr "A bifurcação deve ser do mesmo tipo que o pai" -#: rhodecode/model/validators.py:479 +#: kallithea/model/validators.py:534 msgid "You don't have permissions to create repository in this group" msgstr "Você não tem permissão para criar um repositório neste grupo" -#: rhodecode/model/validators.py:481 +#: kallithea/model/validators.py:536 msgid "no permission to create repository in root location" msgstr "você não tem permissão para criar um repositório na raiz" -#: rhodecode/model/validators.py:518 +#: kallithea/model/validators.py:585 msgid "You don't have permissions to create a group in this location" msgstr "Você não tem permissão para criar um grupo neste local" -#: rhodecode/model/validators.py:559 +#: kallithea/model/validators.py:626 msgid "This username or user group name is not valid" msgstr "Este nome de usuário ou de grupo de usuários não é válido" -#: rhodecode/model/validators.py:652 +#: kallithea/model/validators.py:719 msgid "This is not a valid path" msgstr "Esse não é um caminho válido" -#: rhodecode/model/validators.py:667 +#: kallithea/model/validators.py:734 msgid "This e-mail address is already taken" msgstr "Esse endereço de e-mail já está tomado" -#: rhodecode/model/validators.py:687 +#: kallithea/model/validators.py:754 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "o e-mail \"%(email)s\" não existe." -#: rhodecode/model/validators.py:724 +#: kallithea/model/validators.py:791 msgid "" -"The LDAP Login attribute of the CN must be specified - this is the name of " -"the attribute that is equivalent to \"username\"" -msgstr "O atributo de login LDAP do CN deve ser especificado - isto é o nome do atributo que é equivalente ao 'nome de usuário'" - -#: rhodecode/model/validators.py:737 +"The LDAP Login attribute of the CN must be specified - this is the name " +"of the attribute that is equivalent to \"username\"" +msgstr "" +"O atributo de login LDAP do CN deve ser especificado - isto é o nome do " +"atributo que é equivalente ao 'nome de usuário'" + +#: kallithea/model/validators.py:804 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" msgstr "" - -#: rhodecode/model/validators.py:769 +"As revisões %(revs)s já fazem parte de um pull request ou já setaram o " +"estado" + +#: kallithea/model/validators.py:836 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "Por favor, forneça um endereço válido IPv4 ou IPv6" -#: rhodecode/model/validators.py:770 -#, python-format -msgid "" -"The network size (bits) must be within the range of 0-32 (not %(bits)r)" +#: kallithea/model/validators.py:837 +#, python-format +msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" msgstr "O tamanho da rede (bits) deve estar no intervalo 0-32 (não %(bits)r)" -#: rhodecode/model/validators.py:803 +#: kallithea/model/validators.py:870 msgid "Key name can only consist of letters, underscore, dash or numbers" msgstr "O nome da chave só pode conter letras, underscore, hífen ou dígitos" -#: rhodecode/model/validators.py:817 +#: kallithea/model/validators.py:884 msgid "Filename cannot be inside a directory" msgstr "O nome de arquivo não pode estar dentro de um diretório" -#: rhodecode/templates/index.html:5 +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" +msgstr "" + +#: kallithea/templates/index.html:5 msgid "Dashboard" msgstr "Painel de Controle" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/repo_switcher_list.html:4 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/users/user_edit_my_account.html:31 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/bookmarks/bookmarks.html:9 -#: rhodecode/templates/branches/branches.html:9 -#: rhodecode/templates/journal/journal.html:9 -#: rhodecode/templates/journal/journal.html:46 -#: rhodecode/templates/journal/journal.html:47 -#: rhodecode/templates/tags/tags.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 msgid "quick filter..." msgstr "filtro rápido..." -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/admin/repos/repos.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 msgid "repositories" msgstr "repositórios" -#: rhodecode/templates/index_base.html:13 -#: rhodecode/templates/index_base.html:18 -#: rhodecode/templates/admin/repos/repo_add.html:5 -#: rhodecode/templates/admin/repos/repos.html:22 -msgid "Add repository" -msgstr "Adicionar repositório" - -#: rhodecode/templates/index_base.html:15 -#: rhodecode/templates/index_base.html:20 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:31 -msgid "Add group" -msgstr "Adicionar grupo" - -#: rhodecode/templates/index_base.html:27 -msgid "Edit group" -msgstr "Editar grupo" - -#: rhodecode/templates/index_base.html:27 +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" +msgstr "" + +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:32 msgid "You have admin right to this group, and can edit it" msgstr "Você tem direitos de administrador neste grupo e pode editá-lo" -#: rhodecode/templates/index_base.html:40 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:33 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:38 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:43 -#: rhodecode/templates/admin/users_groups/users_group_add.html:32 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 -#: rhodecode/templates/admin/users_groups/users_groups.html:37 -msgid "Group name" -msgstr "Nome do grupo" - -#: rhodecode/templates/index_base.html:41 -#: rhodecode/templates/index_base.html:123 -#: rhodecode/templates/admin/repos/repo_add_base.html:56 -#: rhodecode/templates/admin/repos/repo_edit.html:68 -#: rhodecode/templates/admin/repos/repos.html:75 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:42 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:47 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:44 -#: rhodecode/templates/email_templates/changeset_comment.html:9 -#: rhodecode/templates/email_templates/pull_request.html:9 -#: rhodecode/templates/forks/fork.html:56 -#: rhodecode/templates/pullrequests/pullrequest.html:43 -#: rhodecode/templates/pullrequests/pullrequest_show.html:81 -#: rhodecode/templates/summary/summary.html:106 +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" +msgstr "" + +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 msgid "Description" msgstr "Descrição" -#: rhodecode/templates/index_base.html:51 -#: rhodecode/templates/admin/permissions/permissions.html:55 -#: rhodecode/templates/admin/repos/repo_add_base.html:29 -#: rhodecode/templates/admin/repos/repo_edit.html:50 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:57 -#: rhodecode/templates/forks/fork.html:47 -msgid "Repository group" -msgstr "Grupo de repositórios" - -#: rhodecode/templates/index_base.html:121 -#: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit.html:32 -#: rhodecode/templates/admin/repos/repos.html:73 -#: rhodecode/templates/admin/users/user_edit_my_account.html:172 -#: rhodecode/templates/base/perms_summary.html:37 -#: rhodecode/templates/bookmarks/bookmarks.html:48 -#: rhodecode/templates/bookmarks/bookmarks_data.html:6 -#: rhodecode/templates/branches/branches.html:47 -#: rhodecode/templates/branches/branches_data.html:6 -#: rhodecode/templates/files/files_browser.html:47 -#: rhodecode/templates/journal/journal.html:193 -#: rhodecode/templates/journal/journal.html:283 -#: rhodecode/templates/summary/summary.html:55 -#: rhodecode/templates/summary/summary.html:124 -#: rhodecode/templates/tags/tags.html:48 -#: rhodecode/templates/tags/tags_data.html:6 +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 msgid "Name" msgstr "Nome" -#: rhodecode/templates/index_base.html:124 +#: kallithea/templates/index_base.html:129 msgid "Last Change" msgstr "Última Alteração" -#: rhodecode/templates/index_base.html:126 -#: rhodecode/templates/admin/repos/repos.html:76 -#: rhodecode/templates/admin/users/user_edit_my_account.html:174 -#: rhodecode/templates/journal/journal.html:195 -#: rhodecode/templates/journal/journal.html:285 +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 msgid "Tip" msgstr "Ponta" -#: rhodecode/templates/index_base.html:128 -#: rhodecode/templates/admin/repos/repo_edit.html:114 -#: rhodecode/templates/admin/repos/repos.html:78 +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 msgid "Owner" msgstr "Dono" -#: rhodecode/templates/index_base.html:136 -#: rhodecode/templates/admin/repos/repos.html:86 -#: rhodecode/templates/admin/users/user_edit_my_account.html:183 -#: rhodecode/templates/admin/users/users.html:107 -#: rhodecode/templates/bookmarks/bookmarks.html:74 -#: rhodecode/templates/branches/branches.html:73 -#: rhodecode/templates/journal/journal.html:204 -#: rhodecode/templates/journal/journal.html:294 -#: rhodecode/templates/tags/tags.html:74 +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 msgid "Click to sort ascending" msgstr "Clique para ordenar em ordem crescente" -#: rhodecode/templates/index_base.html:137 -#: rhodecode/templates/admin/repos/repos.html:87 -#: rhodecode/templates/admin/users/user_edit_my_account.html:184 -#: rhodecode/templates/admin/users/users.html:108 -#: rhodecode/templates/bookmarks/bookmarks.html:75 -#: rhodecode/templates/branches/branches.html:74 -#: rhodecode/templates/journal/journal.html:205 -#: rhodecode/templates/journal/journal.html:295 -#: rhodecode/templates/tags/tags.html:75 +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 msgid "Click to sort descending" msgstr "Clique para ordenar em ordem descrescente" -#: rhodecode/templates/index_base.html:138 +#: kallithea/templates/index_base.html:143 msgid "No repositories found." msgstr "Nenhum repositório encontrado." -#: rhodecode/templates/index_base.html:139 -#: rhodecode/templates/admin/repos/repos.html:89 -#: rhodecode/templates/admin/users/user_edit_my_account.html:186 -#: rhodecode/templates/admin/users/users.html:110 -#: rhodecode/templates/bookmarks/bookmarks.html:77 -#: rhodecode/templates/branches/branches.html:76 -#: rhodecode/templates/journal/journal.html:207 -#: rhodecode/templates/journal/journal.html:297 -#: rhodecode/templates/tags/tags.html:77 +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 msgid "Data error." msgstr "Erro de dados." -#: rhodecode/templates/index_base.html:140 -#: rhodecode/templates/admin/repos/repos.html:90 -#: rhodecode/templates/admin/users/user_edit_my_account.html:58 -#: rhodecode/templates/admin/users/user_edit_my_account.html:187 -#: rhodecode/templates/admin/users/users.html:111 -#: rhodecode/templates/bookmarks/bookmarks.html:78 -#: rhodecode/templates/branches/branches.html:77 -#: rhodecode/templates/journal/journal.html:208 -#: rhodecode/templates/journal/journal.html:298 -#: rhodecode/templates/tags/tags.html:78 +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 msgid "Loading..." msgstr "Carregando..." -#: rhodecode/templates/login.html:5 rhodecode/templates/base/base.html:239 +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 msgid "Log In" msgstr "Entrar" -#: rhodecode/templates/login.html:21 +#: kallithea/templates/login.html:30 #, python-format msgid "Log In to %s" msgstr "Log in em %s" -#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20 -#: rhodecode/templates/admin/admin_log.html:5 -#: rhodecode/templates/admin/users/user_add.html:32 -#: rhodecode/templates/admin/users/user_edit.html:57 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:31 -#: rhodecode/templates/admin/users/users.html:77 -#: rhodecode/templates/base/base.html:215 -#: rhodecode/templates/summary/summary.html:123 +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 msgid "Username" msgstr "Nome de usuário" -#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29 -#: rhodecode/templates/admin/ldap/ldap.html:46 -#: rhodecode/templates/admin/users/user_add.html:41 -#: rhodecode/templates/base/base.html:224 +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 msgid "Password" msgstr "Senha" -#: rhodecode/templates/login.html:50 +#: kallithea/templates/login.html:62 msgid "Remember me" msgstr "Lembre-se de mim" -#: rhodecode/templates/login.html:54 +#: kallithea/templates/login.html:66 msgid "Sign In" msgstr "Entrar" -#: rhodecode/templates/login.html:60 +#: kallithea/templates/login.html:72 msgid "Forgot your password ?" msgstr "Esqueceu sua senha ?" -#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:235 +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 msgid "Don't have an account ?" msgstr "Não possui uma conta ?" -#: rhodecode/templates/password_reset.html:5 +#: kallithea/templates/password_reset.html:5 msgid "Password Reset" msgstr "Senha Trocada" -#: rhodecode/templates/password_reset.html:11 -msgid "Reset your password to" -msgstr "Reinicializar sua senha para" - -#: rhodecode/templates/password_reset.html:21 -msgid "Email address" -msgstr "Endereço de e-mail" - -#: rhodecode/templates/password_reset.html:30 -msgid "Reset my password" -msgstr "Reinicializar minha senha" - -#: rhodecode/templates/password_reset.html:31 +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" +msgstr "" + +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "" + +#: kallithea/templates/password_reset.html:64 msgid "Password reset link will be send to matching email address" -msgstr "Link de reinicialização de senha será enviado ao endereço de e-mail correspondente" - -#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74 +msgstr "" +"Link de reinicialização de senha será enviado ao endereço de e-mail " +"correspondente" + +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 msgid "Sign Up" msgstr "Inscrever-se" -#: rhodecode/templates/register.html:11 -msgid "Sign Up to" -msgstr "Inscrever-se em" - -#: rhodecode/templates/register.html:38 +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:58 msgid "Re-enter password" msgstr "Repita a senha" -#: rhodecode/templates/register.html:47 -#: rhodecode/templates/admin/users/user_add.html:59 -#: rhodecode/templates/admin/users/user_edit.html:97 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:62 +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 msgid "First Name" msgstr "Primeiro Nome" -#: rhodecode/templates/register.html:56 -#: rhodecode/templates/admin/users/user_add.html:68 -#: rhodecode/templates/admin/users/user_edit.html:106 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:71 +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 msgid "Last Name" msgstr "Último Nome" -#: rhodecode/templates/register.html:65 -#: rhodecode/templates/admin/users/user_add.html:77 -#: rhodecode/templates/admin/users/user_edit.html:115 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:80 -#: rhodecode/templates/summary/summary.html:125 +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 msgid "Email" msgstr "E-mail" -#: rhodecode/templates/register.html:76 +#: kallithea/templates/register.html:108 msgid "Your account will be activated right after registration" msgstr "Sua conta será ativada logo após o registro ser concluído" -#: rhodecode/templates/register.html:78 +#: kallithea/templates/register.html:110 msgid "Your account must wait for activation by administrator" msgstr "Sua conta precisa esperar ativação por um administrador" -#: rhodecode/templates/repo_switcher_list.html:10 -#: rhodecode/templates/admin/defaults/defaults.html:44 -#: rhodecode/templates/admin/repos/repo_add_base.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:78 -#: rhodecode/templates/data_table/_dt_elements.html:61 -#: rhodecode/templates/summary/summary.html:77 -msgid "Private repository" -msgstr "Repositório privado" - -#: rhodecode/templates/repo_switcher_list.html:12 -#: rhodecode/templates/data_table/_dt_elements.html:63 -#: rhodecode/templates/summary/summary.html:79 -msgid "Public repository" -msgstr "Repositório público" - -#: rhodecode/templates/switch_to_list.html:10 -#: rhodecode/templates/branches/branches_data.html:57 +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 msgid "There are no branches yet" msgstr "Ainda não há ramos" -#: rhodecode/templates/switch_to_list.html:22 -#: rhodecode/templates/tags/tags_data.html:38 +#: kallithea/templates/switch_to_list.html:16 +msgid "Closed Branches" +msgstr "Ramos Fechados" + +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 msgid "There are no tags yet" msgstr "Ainda não há etiquetas" -#: rhodecode/templates/switch_to_list.html:35 -#: rhodecode/templates/bookmarks/bookmarks_data.html:37 +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 msgid "There are no bookmarks yet" msgstr "Ainda não há marcadores" -#: rhodecode/templates/admin/admin.html:5 -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/base/base.html:73 +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 msgid "Admin journal" msgstr "Diário do administrador" -#: rhodecode/templates/admin/admin.html:10 +#: kallithea/templates/admin/admin.html:13 msgid "journal filter..." msgstr "filtro de diário..." -#: rhodecode/templates/admin/admin.html:12 -#: rhodecode/templates/journal/journal.html:11 +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 msgid "filter" msgstr "filtro" -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 #, python-format msgid "%s entry" msgid_plural "%s entries" msgstr[0] "%s entrada" msgstr[1] "%s entradas" -#: rhodecode/templates/admin/admin_log.html:6 -#: rhodecode/templates/admin/repos/repos.html:79 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46 -#: rhodecode/templates/admin/users/user_edit_my_account.html:176 -#: rhodecode/templates/admin/users/users.html:87 -#: rhodecode/templates/admin/users_groups/users_groups.html:40 -#: rhodecode/templates/journal/journal.html:197 -#: rhodecode/templates/journal/journal.html:287 +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 msgid "Action" msgstr "Ação" -#: rhodecode/templates/admin/admin_log.html:7 -#: rhodecode/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" msgstr "Repositório" -#: rhodecode/templates/admin/admin_log.html:8 -#: rhodecode/templates/bookmarks/bookmarks.html:49 -#: rhodecode/templates/bookmarks/bookmarks_data.html:7 -#: rhodecode/templates/branches/branches.html:48 -#: rhodecode/templates/branches/branches_data.html:7 -#: rhodecode/templates/tags/tags.html:49 -#: rhodecode/templates/tags/tags_data.html:7 +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 msgid "Date" msgstr "Data" -#: rhodecode/templates/admin/admin_log.html:9 +#: kallithea/templates/admin/admin_log.html:9 msgid "From IP" msgstr "A partir do IP" -#: rhodecode/templates/admin/admin_log.html:63 +#: kallithea/templates/admin/admin_log.html:63 msgid "No actions yet" msgstr "Ainda não há ações" -#: rhodecode/templates/admin/defaults/defaults.html:5 -#: rhodecode/templates/admin/defaults/defaults.html:25 +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "" +"Comma separated list of plugins. Order of plugins is also order in which " +"Kallithea will try to authenticate user" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "Salvar" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 msgid "Repositories defaults" msgstr "Padrões de repositórios" -#: rhodecode/templates/admin/defaults/defaults.html:11 -#: rhodecode/templates/base/base.html:80 +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 msgid "Defaults" msgstr "Padrões" -#: rhodecode/templates/admin/defaults/defaults.html:35 -#: rhodecode/templates/admin/repos/repo_add_base.html:38 +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 msgid "Type" msgstr "Tipo" -#: rhodecode/templates/admin/defaults/defaults.html:48 -#: rhodecode/templates/admin/repos/repo_add_base.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:82 -#: rhodecode/templates/forks/fork.html:69 +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "Repositório privado" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 msgid "" "Private repositories are only visible to people explicitly added as " "collaborators." -msgstr "Repositórios privados são visíveis somente por pessoas explicitamente adicionadas como colaboradores." - -#: rhodecode/templates/admin/defaults/defaults.html:55 -#: rhodecode/templates/admin/repos/repo_edit.html:87 +msgstr "" +"Repositórios privados são visíveis somente por pessoas explicitamente " +"adicionadas como colaboradores." + +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 msgid "Enable statistics" msgstr "Habilitar estatísticas" -#: rhodecode/templates/admin/defaults/defaults.html:59 -#: rhodecode/templates/admin/repos/repo_edit.html:91 +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." msgstr "Habilitar janela de estatísticas na página de sumário." -#: rhodecode/templates/admin/defaults/defaults.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:96 +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 msgid "Enable downloads" msgstr "Habilitar downloads" -#: rhodecode/templates/admin/defaults/defaults.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:100 +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." msgstr "Habilitar menu de descarregar na página de sumário." -#: rhodecode/templates/admin/defaults/defaults.html:75 -#: rhodecode/templates/admin/repos/repo_edit.html:105 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:64 +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 msgid "Enable locking" msgstr "Habilitar travas" -#: rhodecode/templates/admin/defaults/defaults.html:79 -#: rhodecode/templates/admin/repos/repo_edit.html:109 +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 msgid "Enable lock-by-pulling on repository." msgstr "Habilitar trava-por-pulling no repositório." -#: rhodecode/templates/admin/defaults/defaults.html:84 -#: rhodecode/templates/admin/ldap/ldap.html:89 -#: rhodecode/templates/admin/permissions/permissions.html:122 -#: rhodecode/templates/admin/repos/repo_edit.html:141 -#: rhodecode/templates/admin/repos/repo_edit.html:166 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:72 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:96 -#: rhodecode/templates/admin/settings/hooks.html:73 -#: rhodecode/templates/admin/users/user_add.html:94 -#: rhodecode/templates/admin/users/user_edit.html:140 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:88 -#: rhodecode/templates/admin/users_groups/users_group_add.html:49 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:143 -#: rhodecode/templates/base/default_perms_box.html:53 -msgid "Save" -msgstr "Salvar" - -#: rhodecode/templates/admin/gists/index.html:5 -#: rhodecode/templates/base/base.html:299 -msgid "Gists" -msgstr "Gists" - -#: rhodecode/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "" +"Gist was update since you started editing. Copy your changes and click " +"%(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "Descrição do gist ..." + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "Tempo de vida do Gist" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "Expira" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "nunca" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "Cancelar" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 #, python-format msgid "Private Gists for user %s" msgstr "Gists privados do usuário %s" -#: rhodecode/templates/admin/gists/index.html:12 +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 #, python-format msgid "Public Gists for user %s" msgstr "Gists públicos do usuário %s" -#: rhodecode/templates/admin/gists/index.html:14 +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 msgid "Public Gists" msgstr "Gists Públicos" -#: rhodecode/templates/admin/gists/index.html:31 -#: rhodecode/templates/admin/gists/show.html:24 -#: rhodecode/templates/base/base.html:302 -msgid "Create new gist" -msgstr "Criar novo gist" - -#: rhodecode/templates/admin/gists/index.html:48 +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 msgid "Created" msgstr "Criado" -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/index.html:53 -#: rhodecode/templates/admin/gists/show.html:43 -#: rhodecode/templates/admin/gists/show.html:45 -msgid "Expires" -msgstr "Expira" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/show.html:43 -msgid "never" -msgstr "nunca" - -#: rhodecode/templates/admin/gists/index.html:68 +#: kallithea/templates/admin/gists/index.html:77 msgid "There are no gists yet" msgstr "Não há nenhum gist ainda" -#: rhodecode/templates/admin/gists/new.html:5 -#: rhodecode/templates/admin/gists/new.html:16 -msgid "New gist" -msgstr "Novo gist" - -#: rhodecode/templates/admin/gists/new.html:37 -msgid "Gist description ..." -msgstr "Descrição do gist ..." - -#: rhodecode/templates/admin/gists/new.html:52 -msgid "Create private gist" -msgstr "Criar gist privado" - -#: rhodecode/templates/admin/gists/new.html:53 -msgid "Create public gist" -msgstr "Criar gist público" - -#: rhodecode/templates/admin/gists/new.html:54 -#: rhodecode/templates/admin/permissions/permissions.html:123 -#: rhodecode/templates/admin/permissions/permissions.html:185 -#: rhodecode/templates/admin/repos/repo_edit.html:142 -#: rhodecode/templates/admin/repos/repo_edit.html:167 -#: rhodecode/templates/admin/repos/repo_edit.html:381 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:97 -#: rhodecode/templates/admin/settings/settings.html:115 -#: rhodecode/templates/admin/settings/settings.html:196 -#: rhodecode/templates/admin/settings/settings.html:288 -#: rhodecode/templates/admin/users/user_edit.html:141 -#: rhodecode/templates/admin/users/user_edit.html:198 -#: rhodecode/templates/admin/users/user_edit.html:246 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:89 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:144 -#: rhodecode/templates/base/default_perms_box.html:54 -#: rhodecode/templates/files/files_add.html:80 -#: rhodecode/templates/files/files_edit.html:66 -#: rhodecode/templates/pullrequests/pullrequest.html:86 +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 msgid "Reset" msgstr "Limpar" -#: rhodecode/templates/admin/gists/show.html:5 -msgid "gist" -msgstr "gist" - -#: rhodecode/templates/admin/gists/show.html:9 +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 msgid "Gist" msgstr "Gist" -#: rhodecode/templates/admin/gists/show.html:36 -msgid "Public gist" -msgstr "Gist público" - -#: rhodecode/templates/admin/gists/show.html:38 -msgid "Private gist" -msgstr "Gist privado" - -#: rhodecode/templates/admin/gists/show.html:54 -#: rhodecode/templates/admin/repos/repo_edit.html:299 -#: rhodecode/templates/changeset/changeset_file_comment.html:40 +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "URL" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 msgid "Delete" msgstr "Excluir" -#: rhodecode/templates/admin/gists/show.html:54 -msgid "Confirm to delete this gist" -msgstr "Confirme para excluir este gist" - -#: rhodecode/templates/admin/gists/show.html:63 -#: rhodecode/templates/admin/gists/show.html:84 -#: rhodecode/templates/files/files_edit.html:48 -#: rhodecode/templates/files/files_source.html:25 -#: rhodecode/templates/files/files_source.html:55 -msgid "Show as raw" -msgstr "Mostrar original" - -#: rhodecode/templates/admin/gists/show.html:71 +#: kallithea/templates/admin/gists/show.html:59 +msgid "Confirm to delete this Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "Editar" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:76 msgid "created" msgstr "criado" -#: rhodecode/templates/admin/ldap/ldap.html:5 -msgid "LDAP administration" -msgstr "Administração de LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:11 -#: rhodecode/templates/admin/users/users.html:86 -#: rhodecode/templates/base/base.html:79 -msgid "LDAP" -msgstr "LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:28 -msgid "Connection settings" -msgstr "Configurações de conexão" - -#: rhodecode/templates/admin/ldap/ldap.html:30 -msgid "Enable LDAP" -msgstr "Habilitar LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:34 -msgid "Host" -msgstr "Host" - -#: rhodecode/templates/admin/ldap/ldap.html:38 -msgid "Port" -msgstr "Porta" - -#: rhodecode/templates/admin/ldap/ldap.html:42 -msgid "Account" -msgstr "Conta" - -#: rhodecode/templates/admin/ldap/ldap.html:50 -msgid "Connection security" -msgstr "Segurança da conexão" - -#: rhodecode/templates/admin/ldap/ldap.html:54 -msgid "Certificate Checks" -msgstr "Verificações de Certificados" - -#: rhodecode/templates/admin/ldap/ldap.html:57 -msgid "Search settings" -msgstr "Configurações de busca" - -#: rhodecode/templates/admin/ldap/ldap.html:59 -msgid "Base DN" -msgstr "DN Base" - -#: rhodecode/templates/admin/ldap/ldap.html:63 -msgid "LDAP Filter" -msgstr "Filtro LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:67 -msgid "LDAP Search Scope" -msgstr "Escopo de Buscas LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:70 -msgid "Attribute mappings" -msgstr "Mapeamento de atributos" - -#: rhodecode/templates/admin/ldap/ldap.html:72 -msgid "Login Attribute" -msgstr "Atributo de Login" - -#: rhodecode/templates/admin/ldap/ldap.html:76 -msgid "First Name Attribute" -msgstr "Atributo do Primeiro Nome" - -#: rhodecode/templates/admin/ldap/ldap.html:80 -msgid "Last Name Attribute" -msgstr "Atributo do Último Nome" - -#: rhodecode/templates/admin/ldap/ldap.html:84 -msgid "E-mail Attribute" -msgstr "Atributo de E-mail" - -#: rhodecode/templates/admin/notifications/notifications.html:5 -#: rhodecode/templates/admin/notifications/notifications.html:9 +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "Mostrar original" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "Minha conta" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" +msgstr "Minha Conta" + +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "Seguindo" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "Pull requests" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "Minhas permissões" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "Adicionar" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "excluir" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "Confirme para excluir este email: %s" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "Novo endereço de email" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "Nova senha" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "Altere o seu avatar em" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "Usando" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "" +"Your user is in an external Source of Record; some details cannot be " +"managed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "Mostrar pull requests fechados" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "Abertos por mim" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "Pull request $%s aberto em %s" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "Fechado" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "Confirme para excluir este pull request" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "Não há nada aqui ainda" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "Eu participo em" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "Pull request #%s aberto por %s em %s" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "Nenhum registro encontrado." + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 msgid "My Notifications" msgstr "Minhas Notificações" -#: rhodecode/templates/admin/notifications/notifications.html:29 +#: kallithea/templates/admin/notifications/notifications.html:32 msgid "All" msgstr "Todos" -#: rhodecode/templates/admin/notifications/notifications.html:30 +#: kallithea/templates/admin/notifications/notifications.html:33 msgid "Comments" msgstr "Comentários" -#: rhodecode/templates/admin/notifications/notifications.html:31 -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:8 -msgid "Pull requests" -msgstr "Pull requests" - -#: rhodecode/templates/admin/notifications/notifications.html:35 +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" +msgstr "Pull Requests" + +#: kallithea/templates/admin/notifications/notifications.html:38 msgid "Mark all read" msgstr "Marcar tudo como lido" -#: rhodecode/templates/admin/notifications/notifications_data.html:39 +#: kallithea/templates/admin/notifications/notifications_data.html:40 msgid "No notifications here yet" msgstr "Ainda não há notificações aqui" -#: rhodecode/templates/admin/notifications/show_notification.html:5 -#: rhodecode/templates/admin/notifications/show_notification.html:11 +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 msgid "Show notification" msgstr "Mostrar notificação" -#: rhodecode/templates/admin/notifications/show_notification.html:9 -#: rhodecode/templates/base/base.html:253 +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 msgid "Notifications" msgstr "Notificações" -#: rhodecode/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:5 msgid "Permissions administration" msgstr "Administração de permissões" -#: rhodecode/templates/admin/permissions/permissions.html:11 -#: rhodecode/templates/admin/repos/repo_edit.html:151 -#: rhodecode/templates/admin/repos/repo_edit.html:158 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:81 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:88 -#: rhodecode/templates/admin/users/user_edit.html:150 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:129 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:136 -#: rhodecode/templates/base/base.html:78 +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 msgid "Permissions" msgstr "Permissões" -#: rhodecode/templates/admin/permissions/permissions.html:24 -msgid "Default permissions" -msgstr "Permissões padrão" - -#: rhodecode/templates/admin/permissions/permissions.html:31 +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 msgid "Anonymous access" msgstr "Acesso anônimo" -#: rhodecode/templates/admin/permissions/permissions.html:49 +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without need to log in. Anonymous users use %s " +"user permissions" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 msgid "" "All default permissions on each repository will be reset to chosen " -"permission, note that all custom default permission on repositories will be " -"lost" -msgstr "Todas as permissões padrão em cada repositório serão modificadas para a permissão escolhida, note que todas as permissões padrão customizadas nos repositórios serão perdidas" - -#: rhodecode/templates/admin/permissions/permissions.html:50 -#: rhodecode/templates/admin/permissions/permissions.html:63 -#: rhodecode/templates/admin/permissions/permissions.html:77 +"permission, note that all custom default permission on repositories will " +"be lost" +msgstr "" +"Todas as permissões padrão em cada repositório serão modificadas para a " +"permissão escolhida, note que todas as permissões padrão customizadas nos" +" repositórios serão perdidas" + +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 msgid "Overwrite existing settings" msgstr "Sobrescrever as configurações existentes" -#: rhodecode/templates/admin/permissions/permissions.html:62 +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "Grupo de repositórios" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 msgid "" "All default permissions on each repository group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" -msgstr "Todas as permissões padrão em cada grupo de repositórios serão modificadas para a permissão escolhida, note que todas as permissões padrão customizadas em grupos de repositórios serão perdidas" - -#: rhodecode/templates/admin/permissions/permissions.html:69 +msgstr "" +"Todas as permissões padrão em cada grupo de repositórios serão " +"modificadas para a permissão escolhida, note que todas as permissões " +"padrão customizadas em grupos de repositórios serão perdidas" + +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 msgid "User group" msgstr "Grupo de usuários" -#: rhodecode/templates/admin/permissions/permissions.html:76 +#: kallithea/templates/admin/permissions/permissions_globals.html:53 msgid "" "All default permissions on each user group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" -msgstr "Todas as permissões padrão em cada repositório serão reinicializadas para as permissões escolhidas. Note que todas as permissões padrão customizadas nos repositórios serão perdidas" - -#: rhodecode/templates/admin/permissions/permissions.html:83 +msgstr "" +"Todas as permissões padrão em cada repositório serão reinicializadas para" +" as permissões escolhidas. Note que todas as permissões padrão " +"customizadas nos repositórios serão perdidas" + +#: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" msgstr "Criação de repositório" -#: rhodecode/templates/admin/permissions/permissions.html:91 +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "" +"Write permission to repository groups allows creating repositories inside" +" that group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 msgid "User group creation" msgstr "Criação de grupo de usuários" -#: rhodecode/templates/admin/permissions/permissions.html:99 +#: kallithea/templates/admin/permissions/permissions_globals.html:85 msgid "Repository forking" msgstr "Bifurcação de repositório" -#: rhodecode/templates/admin/permissions/permissions.html:107 +#: kallithea/templates/admin/permissions/permissions_globals.html:93 msgid "Registration" msgstr "Registro" -#: rhodecode/templates/admin/permissions/permissions.html:115 +#: kallithea/templates/admin/permissions/permissions_globals.html:101 msgid "External auth account activation" msgstr "Ativação de autenticação de conta externa" -#: rhodecode/templates/admin/permissions/permissions.html:133 -msgid "Default User Permissions" -msgstr "Permissões Padrão de Usuários" - -#: rhodecode/templates/admin/permissions/permissions.html:144 -#: rhodecode/templates/admin/users/user_edit.html:207 -msgid "Allowed IP addresses" -msgstr "Endereços IP permitidos" - -#: rhodecode/templates/admin/permissions/permissions.html:158 -#: rhodecode/templates/admin/repos/repo_edit.html:340 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#: rhodecode/templates/admin/users/user_edit.html:175 -#: rhodecode/templates/admin/users/user_edit.html:220 -#: rhodecode/templates/admin/users_groups/users_groups.html:54 -#: rhodecode/templates/data_table/_dt_elements.html:122 -#: rhodecode/templates/data_table/_dt_elements.html:136 -msgid "delete" -msgstr "excluir" - -#: rhodecode/templates/admin/permissions/permissions.html:159 -#: rhodecode/templates/admin/users/user_edit.html:221 +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 #, python-format msgid "Confirm to delete this ip: %s" msgstr "Confirme para excluir este IP: %s" -#: rhodecode/templates/admin/permissions/permissions.html:165 -#: rhodecode/templates/admin/users/user_edit.html:227 +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 msgid "All IP addresses are allowed" msgstr "Todos os endereços IP são permitidos" -#: rhodecode/templates/admin/permissions/permissions.html:176 -#: rhodecode/templates/admin/users/user_edit.html:238 +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" msgstr "Novo endereço IP" -#: rhodecode/templates/admin/permissions/permissions.html:184 -#: rhodecode/templates/admin/repos/repo_add_base.html:73 -#: rhodecode/templates/admin/repos/repo_edit.html:380 -#: rhodecode/templates/admin/users/user_edit.html:197 -#: rhodecode/templates/admin/users/user_edit.html:245 -msgid "Add" -msgstr "Adicionar" - -#: rhodecode/templates/admin/repos/repo_add.html:12 -#: rhodecode/templates/admin/repos/repo_add.html:16 -#: rhodecode/templates/base/base.html:74 rhodecode/templates/base/base.html:88 -#: rhodecode/templates/base/base.html:116 -#: rhodecode/templates/base/base.html:275 -msgid "Repositories" -msgstr "Repositórios" - -#: rhodecode/templates/admin/repos/repo_add.html:19 -msgid "Add new" -msgstr "Adicionar novo" - -#: rhodecode/templates/admin/repos/repo_add_base.html:20 -#: rhodecode/templates/summary/summary.html:96 -#: rhodecode/templates/summary/summary.html:97 -msgid "Clone from" -msgstr "Clonar de" - -#: rhodecode/templates/admin/repos/repo_add_base.html:24 -#: rhodecode/templates/admin/repos/repo_edit.html:45 -msgid "Optional http[s] url from which repository should be cloned." -msgstr "URL opcional http[s] da qual o repositório deve ser clonado." - -#: rhodecode/templates/admin/repos/repo_add_base.html:33 -#: rhodecode/templates/forks/fork.html:51 -msgid "Optionaly select a group to put this repository into." -msgstr "Opcionalmente, selecione um grupo no qual colocar este repositório" - -#: rhodecode/templates/admin/repos/repo_add_base.html:42 -msgid "Type of repository to create." -msgstr "Tipo de repositório a criar." - -#: rhodecode/templates/admin/repos/repo_add_base.html:47 -#: rhodecode/templates/admin/repos/repo_edit.html:59 -#: rhodecode/templates/forks/fork.html:38 -msgid "Landing revision" -msgstr "Revisão de pouso" - -#: rhodecode/templates/admin/repos/repo_add_base.html:51 -#: rhodecode/templates/admin/repos/repo_edit.html:63 -#: rhodecode/templates/forks/fork.html:42 -msgid "Default revision for files page, downloads, whoosh and readme" -msgstr "Revisão padrão para página de arquivos, downloads, whoosh e readme" - -#: rhodecode/templates/admin/repos/repo_add_base.html:60 -#: rhodecode/templates/admin/repos/repo_edit.html:72 -#: rhodecode/templates/forks/fork.html:60 -msgid "" -"Keep it short and to the point. Use a README file for longer descriptions." -msgstr "Seja sucinto e objetivo. Use um arquivo README para descrições mais longas." - -#: rhodecode/templates/admin/repos/repo_edit.html:8 -msgid "Edit repository" -msgstr "Editar repositório" - -#: rhodecode/templates/admin/repos/repo_edit.html:12 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:11 -#: rhodecode/templates/base/base.html:81 -#: rhodecode/templates/base/base.html:134 -#: rhodecode/templates/summary/summary.html:212 +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "Adicionar grupo de repositórios" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "Grupo de repositórios" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "Nome do grupo" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "Progenitor do grupo" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 msgid "Settings" msgstr "Configurações" -#: rhodecode/templates/admin/repos/repo_edit.html:36 -msgid "Non-changeable id" -msgstr "ID inalterável" - -#: rhodecode/templates/admin/repos/repo_edit.html:41 -msgid "Clone uri" -msgstr "URI de clonagem" - -#: rhodecode/templates/admin/repos/repo_edit.html:54 -msgid "Optional select a group to put this repository into." -msgstr "Opcionalmente selecione um grupo no qual colocar esse repositório." - -#: rhodecode/templates/admin/repos/repo_edit.html:119 -msgid "Change owner of this repository." -msgstr "Mudar o dono desse repositório." - -#: rhodecode/templates/admin/repos/repo_edit.html:177 -msgid "Advanced settings" -msgstr "Configurações avançadas" - -#: rhodecode/templates/admin/repos/repo_edit.html:180 -msgid "Statistics" -msgstr "Estatísticas" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Reset current statistics" -msgstr "Reinicializar estatísticas atuais" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Confirm to remove current statistics" -msgstr "Confirma remover atuais estatísticas" - -#: rhodecode/templates/admin/repos/repo_edit.html:187 -msgid "Fetched to rev" -msgstr "Trazida à rev" - -#: rhodecode/templates/admin/repos/repo_edit.html:188 -msgid "Stats gathered" -msgstr "Estatísticas coletadas" - -#: rhodecode/templates/admin/repos/repo_edit.html:196 -msgid "Remote" -msgstr "Remoto" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Pull changes from remote location" -msgstr "Realizar pull de alterações a partir de localização remota" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Confirm to pull changes from remote side" -msgstr "Confirma realizar pull de alterações a partir de lado remoto" - -#: rhodecode/templates/admin/repos/repo_edit.html:211 -msgid "Cache" -msgstr "Cache" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Invalidate repository cache" -msgstr "Invalidar cache do repositório" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Confirm to invalidate repository cache" -msgstr "Confirma invalidar cache do repositório" - -#: rhodecode/templates/admin/repos/repo_edit.html:218 -msgid "" -"Manually invalidate cache for this repository. On first access repository " -"will be cached again" -msgstr "Invalidar manualmente o cache deste repositório. No próximo acesso o repositório será cacheado novamente" - -#: rhodecode/templates/admin/repos/repo_edit.html:223 -msgid "List of cached values" -msgstr "Lista de valores cacheados" - -#: rhodecode/templates/admin/repos/repo_edit.html:226 -msgid "Prefix" -msgstr "Prefixo" - -#: rhodecode/templates/admin/repos/repo_edit.html:227 -msgid "Key" -msgstr "Chave" - -#: rhodecode/templates/admin/repos/repo_edit.html:228 -#: rhodecode/templates/admin/users/user_add.html:86 -#: rhodecode/templates/admin/users/user_edit.html:124 -#: rhodecode/templates/admin/users/users.html:84 -#: rhodecode/templates/admin/users_groups/users_group_add.html:41 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 -#: rhodecode/templates/admin/users_groups/users_groups.html:39 -msgid "Active" -msgstr "Ativo" - -#: rhodecode/templates/admin/repos/repo_edit.html:243 -#: rhodecode/templates/base/base.html:292 -#: rhodecode/templates/base/base.html:293 -msgid "Public journal" -msgstr "Diário público" - -#: rhodecode/templates/admin/repos/repo_edit.html:249 -msgid "Remove from public journal" -msgstr "Remover do diário público" - -#: rhodecode/templates/admin/repos/repo_edit.html:251 -msgid "Add to public journal" -msgstr "Adicionar ao diário público" - -#: rhodecode/templates/admin/repos/repo_edit.html:256 -msgid "" -"All actions made on this repository will be accessible to everyone in public" -" journal" -msgstr "Todas as ações feitas nesse repositório serão acessíveis a todos no diário público" - -#: rhodecode/templates/admin/repos/repo_edit.html:263 -msgid "Locking" -msgstr "Travamento" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Unlock locked repo" -msgstr "Destravar repo travado" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Confirm to unlock repository" -msgstr "Confirme para destravar repositório" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Lock repo" -msgstr "Travar repo" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Confirm to lock repository" -msgstr "Confirme para travar repositório" - -#: rhodecode/templates/admin/repos/repo_edit.html:272 -msgid "Repository is not locked" -msgstr "Repositório não está travado" - -#: rhodecode/templates/admin/repos/repo_edit.html:277 -msgid "" -"Force locking on repository. Works only when anonymous access is disabled" -msgstr "Forçar travamento no repositório. Só funciona quando o acesso anônimo está desabilitado" - -#: rhodecode/templates/admin/repos/repo_edit.html:284 -msgid "Set as fork of" -msgstr "Marque como bifurcação de" - -#: rhodecode/templates/admin/repos/repo_edit.html:289 -msgid "Set" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:293 -msgid "Manually set this repository as a fork of another from the list" -msgstr "Marque manualmente este repositório como uma bifurcação de um outro da lista" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Remove this repository" -msgstr "Remover deste repositório" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Confirm to delete this repository" -msgstr "Confirma excluir este repositório" - -#: rhodecode/templates/admin/repos/repo_edit.html:310 -#, python-format -msgid "this repository has %s fork" -msgid_plural "this repository has %s forks" -msgstr[0] "este repositório tem %s bifurcação" -msgstr[1] "este repositório tem %s bifurcações" - -#: rhodecode/templates/admin/repos/repo_edit.html:311 -msgid "Detach forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:312 -msgid "Delete forks" -msgstr "Excluir bifurcações" - -#: rhodecode/templates/admin/repos/repo_edit.html:315 -msgid "" -"This repository will be renamed in a special way in order to be unaccesible " -"for RhodeCode and VCS systems. If you need to fully delete it from file " -"system please do it manually" -msgstr "Este repositório será renomeado de um modo especial para não ser mais acessívei pelo RhodeCode ou outros sistemas VCS. Se você precisa excluí-lo totalmente do sistema de arquivos, por favor, faça-o manualmente" - -#: rhodecode/templates/admin/repos/repo_edit.html:329 -msgid "Extra fields" -msgstr "Campos extras" - -#: rhodecode/templates/admin/repos/repo_edit.html:341 -#, python-format -msgid "Confirm to delete this field: %s" -msgstr "Confirme para excluir este campo: %s" - -#: rhodecode/templates/admin/repos/repo_edit.html:355 -msgid "New field key" -msgstr "Próxima chave de campo" - -#: rhodecode/templates/admin/repos/repo_edit.html:363 -msgid "New field label" -msgstr "Próximo rótulo de campo" - -#: rhodecode/templates/admin/repos/repo_edit.html:366 -msgid "Enter short label" -msgstr "Entre com o rótulo curto" - -#: rhodecode/templates/admin/repos/repo_edit.html:372 -msgid "New field description" -msgstr "Nova descrição de campo" - -#: rhodecode/templates/admin/repos/repo_edit.html:375 -msgid "Enter description of a field" -msgstr "Entre com a descrição de um campo" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:3 -msgid "none" -msgstr "nenhum" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:4 -msgid "read" -msgstr "ler" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:5 -msgid "write" -msgstr "escrever" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:6 -msgid "admin" -msgstr "administrador" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:7 -msgid "member" -msgstr "membro" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:16 -msgid "private repository" -msgstr "repositório privado" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:19 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:28 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:20 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:35 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:20 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:35 -msgid "default" -msgstr "padrão" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:33 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:58 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:25 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:55 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:25 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:55 -msgid "revoke" -msgstr "revogar" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:83 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:81 -msgid "Add another member" -msgstr "Adicionar outro membro" - -#: rhodecode/templates/admin/repos/repos.html:5 -msgid "Repositories administration" -msgstr "Administração de repositórios" - -#: rhodecode/templates/admin/repos/repos.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account.html:185 -#: rhodecode/templates/admin/users/users.html:109 -#: rhodecode/templates/bookmarks/bookmarks.html:76 -#: rhodecode/templates/branches/branches.html:75 -#: rhodecode/templates/journal/journal.html:206 -#: rhodecode/templates/journal/journal.html:296 -#: rhodecode/templates/tags/tags.html:76 -msgid "No records found." -msgstr "Nenhum registro encontrado." - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:87 -msgid "apply to children" -msgstr "aplicar aos filhos" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:88 -msgid "" -"Set or revoke permission to all children of that group, including non-" -"private repositories and other groups" -msgstr "Dar ou revocar permissão de todos os filhos daquele grupo, incluindo repositórios públicos e outros grupos" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:4 -#, python-format -msgid "%s Group Dashboard" -msgstr "Dashboard de Grupo %s" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:9 -msgid "Home" -msgstr "Início" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:13 -msgid "with" -msgstr "com" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5 -msgid "Add repository group" -msgstr "Adicionar grupo de repositórios" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:16 -#: rhodecode/templates/base/base.html:75 rhodecode/templates/base/base.html:91 -msgid "Repository groups" -msgstr "Grupo de repositórios" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:13 -msgid "Add new repository group" -msgstr "Adicionar novo grupo de repositórios" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:51 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:56 -msgid "Group parent" -msgstr "Progenitor do grupo" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:59 -msgid "save" -msgstr "salvar" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5 -msgid "Edit repository group" -msgstr "Editar grupo de repositórios" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:13 -#, python-format -msgid "Edit repository group %s" -msgstr "Editar grupo de repositórios %s" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:27 -msgid "Add child group" -msgstr "Adicionar grupo filho" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:68 -msgid "" -"Enable lock-by-pulling on group. This option will be applied to all other " -"groups and repositories inside" -msgstr "Habilitar trava-por-pulling no grupo. Esta opção será aplicada a todos os outros grupos e repositórios dentro deles" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5 -msgid "Repository groups administration" -msgstr "Administração de grupos de repositórios" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:45 -msgid "Number of toplevel repositories" -msgstr "Número de repositórios de nível superior" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:64 -#: rhodecode/templates/admin/users_groups/users_groups.html:48 -#: rhodecode/templates/changeset/changeset_file_comment.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:171 -msgid "Edit" -msgstr "Editar" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:65 -#: rhodecode/templates/admin/users_groups/users_groups.html:49 -#: rhodecode/templates/base/perms_summary.html:29 -#: rhodecode/templates/base/perms_summary.html:60 -#: rhodecode/templates/base/perms_summary.html:62 -#: rhodecode/templates/data_table/_dt_elements.html:116 -#: rhodecode/templates/data_table/_dt_elements.html:117 -#: rhodecode/templates/data_table/_dt_elements.html:130 -#: rhodecode/templates/data_table/_dt_elements.html:131 -msgid "edit" -msgstr "editar" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "Criado em" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 #, python-format msgid "Confirm to delete this group: %s with %s repository" msgid_plural "Confirm to delete this group: %s with %s repositories" msgstr[0] "Confirme para excluir este grupo: %s com %s repositório" msgstr[1] "Confirme para excluir este grupo: %s com %s repositórios" -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:78 -msgid "There are no repository groups yet" -msgstr "Não há nenhum grupo de repositório ainda" - -#: rhodecode/templates/admin/settings/hooks.html:5 -#: rhodecode/templates/admin/settings/settings.html:5 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "nenhum" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "ler" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "escrever" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "administrador" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "padrão" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "revogar" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "Adicionar novo" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "aplicar aos filhos" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "" +"Set or revoke permission to all children of that group, including non-" +"private repositories and other groups if selected." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "" +"Enable lock-by-pulling on group. This option will be applied to all other" +" groups and repositories inside" +msgstr "" +"Habilitar trava-por-pulling no grupo. Esta opção será aplicada a todos os" +" outros grupos e repositórios dentro deles" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "%s Repository group dashboard" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "Início" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "com" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "Administração de grupos de repositórios" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "Número de repositórios de nível superior" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "Adicionar repositório" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "Clonar de" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "URL opcional http[s] da qual o repositório deve ser clonado." + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "" +"Seja sucinto e objetivo. Use um arquivo README para descrições mais " +"longas." + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "Opcionalmente, selecione um grupo no qual colocar este repositório" + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "Tipo de repositório a criar." + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "Revisão de pouso" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is beeing created, you will be redirected " +"when this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:42 +msgid "" +"We're sorry but error occured during this operation. Please check your " +"Kallithea server logs, or contact administrator." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, python-format +msgid "%s repository settings" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "Campos extras" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +msgid "Remote" +msgstr "Remoto" + +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "Estatísticas" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "Bifurcação de" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "" +"Marque manualmente este repositório como uma bifurcação de um outro da " +"lista" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Remove from public journal" +msgstr "Remover do diário público" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +msgid "Add to public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 +msgid "" +"All actions made on this repository will be accessible to everyone in " +"public journal" +msgstr "" +"Todas as ações feitas nesse repositório serão acessíveis a todos no " +"diário público" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 +msgid "Confirm to unlock repository" +msgstr "Confirme para destravar repositório" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 +msgid "Confirm to lock repository" +msgstr "Confirme para travar repositório" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 +msgid "Repository is not locked" +msgstr "Repositório não está travado" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 +msgid "" +"Force locking on repository. Works only when anonymous access is " +"disabled. Trigering a pull locks repository by user who pulled, only the " +"same user can unlock by doing a push" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "Confirma excluir esse repositório: %s" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +msgid "Delete this repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 +#, python-format +msgid "this repository has %s fork" +msgid_plural "this repository has %s forks" +msgstr[0] "este repositório tem %s bifurcação" +msgstr[1] "este repositório tem %s bifurcações" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 +msgid "Detach forks" +msgstr "Desassociar bifurcações" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 +msgid "Delete forks" +msgstr "Excluir bifurcações" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "" +"This repository will be renamed in a special way in order to be " +"unaccesible for Kallithea and VCS systems. If you need to fully delete it" +" from file system please do it manually" +msgstr "" +"Este repositório será renomeado de um modo especial para não ser mais " +"acessívei pelo Kallithea ou outros sistemas VCS. Se você precisa " +"excluí-lo totalmente do sistema de arquivos, por favor, faça-o " +"manualmente" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "Invalidar cache do repositório" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "Confirma invalidar cache do repositório" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 +msgid "" +"Manually invalidate cache for this repository. On first access repository" +" will be cached again" +msgstr "" +"Invalidar manualmente o cache deste repositório. No próximo acesso o " +"repositório será cacheado novamente" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "Lista de valores cacheados" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "Prefixo" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "Chave" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "Ativo" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#, python-format +msgid "Confirm to delete this field: %s" +msgstr "Confirme para excluir este campo: %s" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 +msgid "New field key" +msgstr "Próxima chave de campo" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 +msgid "New field label" +msgstr "Próximo rótulo de campo" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 +msgid "Enter short label" +msgstr "Entre com o rótulo curto" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 +msgid "New field description" +msgstr "Nova descrição de campo" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +msgid "Enter description of a field" +msgstr "Entre com a descrição de um campo" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 +msgid "private repository" +msgstr "repositório privado" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "Realizar pull de alterações a partir de localização remota" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "Confirma realizar pull de alterações a partir de lado remoto" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "ID inalterável" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 +msgid "" +"In case this repository is renamed or moved into another group the " +"repository url changes.\n" +" Using above url guarantees that this " +"repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases" +" that you need to hardcode the url into 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "URI de clonagem" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "editar" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "Opcionalmente selecione um grupo no qual colocar esse repositório." + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "Revisão padrão para página de arquivos, downloads, whoosh e readme" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "Mudar o dono desse repositório." + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "Confirma remover atuais estatísticas" + +#: kallithea/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "Administração de repositórios" + +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 msgid "Settings administration" msgstr "Administração de configurações" -#: rhodecode/templates/admin/settings/hooks.html:24 -msgid "Built in hooks - read only" -msgstr "Ganchos pré-definidos - somente leitura" - -#: rhodecode/templates/admin/settings/hooks.html:40 -msgid "Custom hooks" -msgstr "Ganchos customizados" - -#: rhodecode/templates/admin/settings/hooks.html:56 -msgid "remove" -msgstr "remover" - -#: rhodecode/templates/admin/settings/hooks.html:88 -msgid "Failed to remove hook" -msgstr "Falha ao remover gancho" - -#: rhodecode/templates/admin/settings/settings.html:26 -msgid "Remap and rescan repositories" -msgstr "Remapear e varrer novamente repositórios" - -#: rhodecode/templates/admin/settings/settings.html:34 -msgid "Rescan option" -msgstr "Opção de varredura" - -#: rhodecode/templates/admin/settings/settings.html:40 -msgid "" -"In case a repository was deleted from filesystem and there are leftovers in " -"the database check this option to scan obsolete data in database and remove " -"it." -msgstr "Caso um repositório tenha sido excluído do sistema de arquivos e haja restos no banco de dados, marque esta opção para varrer dados obsoletos no banco e removê-los." - -#: rhodecode/templates/admin/settings/settings.html:41 -msgid "Destroy old data" -msgstr "Destruir dados antigos" - -#: rhodecode/templates/admin/settings/settings.html:43 -msgid "" -"Rescan repositories location for new repositories. Also deletes obsolete if " -"`destroy` flag is checked " -msgstr "Local de varredura para novos repositórios. Também exclui obsoletos se a opção `destruir` estiver habilitada" - -#: rhodecode/templates/admin/settings/settings.html:48 -msgid "Rescan repositories" -msgstr "Varrer repositórios" - -#: rhodecode/templates/admin/settings/settings.html:54 -msgid "Whoosh indexing" -msgstr "Indexação do Whoosh" - -#: rhodecode/templates/admin/settings/settings.html:62 -msgid "Index build option" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:67 -msgid "Build from scratch" -msgstr "Construir do zero" - -#: rhodecode/templates/admin/settings/settings.html:73 -msgid "Reindex" -msgstr "Reindexar" - -#: rhodecode/templates/admin/settings/settings.html:79 -msgid "Global application settings" -msgstr "Configurações globais da aplicação" - -#: rhodecode/templates/admin/settings/settings.html:88 +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "Ganchos" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:16 +msgid "SMTP auth" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:39 +msgid "Send" +msgstr "Enviar" + +#: kallithea/templates/admin/settings/settings_global.html:8 msgid "Site branding" msgstr "Marca do site" -#: rhodecode/templates/admin/settings/settings.html:97 +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:18 msgid "HTTP authentication realm" msgstr "Realm de autenticação HTTP" -#: rhodecode/templates/admin/settings/settings.html:106 +#: kallithea/templates/admin/settings/settings_global.html:27 msgid "Google Analytics code" msgstr "Código do Google Analytics" -#: rhodecode/templates/admin/settings/settings.html:114 -#: rhodecode/templates/admin/settings/settings.html:195 -#: rhodecode/templates/admin/settings/settings.html:287 +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:50 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 msgid "Save settings" msgstr "Salvar configurações" -#: rhodecode/templates/admin/settings/settings.html:121 -msgid "Visualisation settings" -msgstr "Configurações de visualização" - -#: rhodecode/templates/admin/settings/settings.html:129 -msgid "General" -msgstr "Geral" - -#: rhodecode/templates/admin/settings/settings.html:134 -msgid "Use repository extra fields" -msgstr "Usar campos extras do repositório" - -#: rhodecode/templates/admin/settings/settings.html:136 -msgid "Allows storing additional customized fields per repository." -msgstr "Permite armazenar campos customizados adicionais por repositório." - -#: rhodecode/templates/admin/settings/settings.html:139 -msgid "Show RhodeCode version" -msgstr "Mostrar versão do RhodeCode" - -#: rhodecode/templates/admin/settings/settings.html:141 -msgid "Shows or hides displayed version of RhodeCode in the footer" -msgstr "Mostra ou esconde a versão do RhodeCode no rodapé" - -#: rhodecode/templates/admin/settings/settings.html:146 -msgid "Dashboard items" -msgstr "Itens do dashboard" - -#: rhodecode/templates/admin/settings/settings.html:150 +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "" +"Hooks can be used to trigger actions on certain events such as push / " +"pull. They can trigger Python functions or external applications." +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 +msgid "Custom hooks" +msgstr "Ganchos customizados" + +#: kallithea/templates/admin/settings/settings_hooks.html:69 +msgid "Failed to remove hook" +msgstr "Falha ao remover gancho" + +#: kallithea/templates/admin/settings/settings_mapping.html:6 +msgid "Rescan option" +msgstr "Opção de varredura" + +#: kallithea/templates/admin/settings/settings_mapping.html:11 +msgid "Destroy old data" +msgstr "Destruir dados antigos" + +#: kallithea/templates/admin/settings/settings_mapping.html:13 +msgid "" +"In case a repository was deleted from filesystem and it still exists in " +"the database check this option to scan obsolete data in database and " +"remove it." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "Invalidar o cache para todos os repositórios" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 +msgid "" +"Each cache data for repositories will be cleaned with this option " +"selected. Use this to reload data and clear cache keys." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 msgid "" -"Number of items displayed in lightweight dashboard before pagination is " -"shown." -msgstr "Número de itens apresentados no dashboard leve antes de mostrar a paginação." - -#: rhodecode/templates/admin/settings/settings.html:155 -msgid "Icons" -msgstr "Ícones" - -#: rhodecode/templates/admin/settings/settings.html:160 -msgid "Show public repo icon on repositories" -msgstr "Mostrar ícone de repositório público nos repositórios" - -#: rhodecode/templates/admin/settings/settings.html:164 -msgid "Show private repo icon on repositories" -msgstr "Mostrar ícone de repositório privado nos repositórios" - -#: rhodecode/templates/admin/settings/settings.html:166 -msgid "Show public/private icons next to repositories names" -msgstr "Mostrar ícones público/privado ao lado dos nomes dos repositórios" - -#: rhodecode/templates/admin/settings/settings.html:172 -msgid "Meta-Tagging" -msgstr "Meta-Tagging" - -#: rhodecode/templates/admin/settings/settings.html:177 -msgid "Stylify recognised metatags:" -msgstr "Estilizar as metatags reconhecidas:" - -#: rhodecode/templates/admin/settings/settings.html:204 -msgid "VCS settings" -msgstr "Configurações de VCS" - -#: rhodecode/templates/admin/settings/settings.html:213 +"Verify if Kallitheas GIT hooks are installed for each repository. Current" +" hooks will be updated to latest version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:7 +msgid "Index build option" +msgstr "Opção de construção do índice" + +#: kallithea/templates/admin/settings/settings_search.html:12 +msgid "Build from scratch" +msgstr "Construir do zero" + +#: kallithea/templates/admin/settings/settings_search.html:15 +msgid "" +"This option completely reindex all the files within Kallithea for proper " +"fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:21 +msgid "Reindex" +msgstr "Reindexar" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 msgid "Web" msgstr "Web" -#: rhodecode/templates/admin/settings/settings.html:218 +#: kallithea/templates/admin/settings/settings_vcs.html:11 msgid "Require SSL for vcs operations" msgstr "Requer SSL para operações de VCS" -#: rhodecode/templates/admin/settings/settings.html:220 +#: kallithea/templates/admin/settings/settings_vcs.html:13 msgid "" -"RhodeCode will require SSL for pushing or pulling. If SSL is missing it will" -" return HTTP Error 406: Not Acceptable" -msgstr "O RhodeCode vai requerer SSL para push ou pull. Conexões não-SSL vão retornar HTTP Error 406: Not Acceptable" - -#: rhodecode/templates/admin/settings/settings.html:226 -msgid "Hooks" -msgstr "Ganchos" - -#: rhodecode/templates/admin/settings/settings.html:231 -msgid "Update repository after push (hg update)" -msgstr "Atualizar repositório após realizar push (hg update)" - -#: rhodecode/templates/admin/settings/settings.html:235 +"Activate to set Kallithea to require SSL for pushing or pulling. If SSL " +"certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 msgid "Show repository size after push" msgstr "Mostrar tamanho do repositório após o push" -#: rhodecode/templates/admin/settings/settings.html:239 +#: kallithea/templates/admin/settings/settings_vcs.html:28 msgid "Log user push commands" msgstr "Armazenar registro de comandos de push dos usuários" -#: rhodecode/templates/admin/settings/settings.html:243 +#: kallithea/templates/admin/settings/settings_vcs.html:32 msgid "Log user pull commands" msgstr "Armazenar registro de comandos de pull dos usuários" -#: rhodecode/templates/admin/settings/settings.html:247 -msgid "Advanced setup" -msgstr "Configuração avançada" - -#: rhodecode/templates/admin/settings/settings.html:252 +#: kallithea/templates/admin/settings/settings_vcs.html:36 +msgid "Update repository after push (hg update)" +msgstr "Atualizar repositório após realizar push (hg update)" + +#: kallithea/templates/admin/settings/settings_vcs.html:42 msgid "Mercurial Extensions" msgstr "Extensões do Mercurial" -#: rhodecode/templates/admin/settings/settings.html:257 +#: kallithea/templates/admin/settings/settings_vcs.html:47 msgid "Enable largefiles extension" msgstr "Habilitar extensão largefiles" -#: rhodecode/templates/admin/settings/settings.html:261 +#: kallithea/templates/admin/settings/settings_vcs.html:51 msgid "Enable hgsubversion extension" msgstr "Habilitar extensão hgsubversion" -#: rhodecode/templates/admin/settings/settings.html:263 +#: kallithea/templates/admin/settings/settings_vcs.html:53 msgid "" -"Requires hgsubversion library installed. Allows cloning from svn remote " -"locations" -msgstr "Requer que a biblioteca hgsubversion estaja instalada. Permite clonagem de remotos SVN" - -#: rhodecode/templates/admin/settings/settings.html:274 +"Requires hgsubversion library to be installed. Allows cloning remote SVN " +"repositories and migrates them to Mercurial type." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 msgid "Repositories location" msgstr "Localização dos repositórios" -#: rhodecode/templates/admin/settings/settings.html:279 +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting" +" take effect." +msgstr "" +"Clique para destravar. Você deve reiniciar o Kallithea para que esta " +"configuração tenha efeito." + +#: kallithea/templates/admin/settings/settings_vcs.html:72 msgid "" -"Click to unlock. You must restart RhodeCode in order to make this setting " -"take effect." -msgstr "Clique para destravar. Você deve reiniciar o RhodeCode para que esta configuração tenha efeito." - -#: rhodecode/templates/admin/settings/settings.html:280 -#: rhodecode/templates/base/base.html:143 -msgid "Unlock" -msgstr "Destravar" - -#: rhodecode/templates/admin/settings/settings.html:282 +"Filesystem location where repositories should be stored. After changing " +"this value a restart and rescan of the repository folder are required." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:8 +msgid "General" +msgstr "Geral" + +#: kallithea/templates/admin/settings/settings_visual.html:13 +msgid "Use repository extra fields" +msgstr "Usar campos extras do repositório" + +#: kallithea/templates/admin/settings/settings_visual.html:15 +msgid "Allows storing additional customized fields per repository." +msgstr "Permite armazenar campos customizados adicionais por repositório." + +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "Mostrar versão do Kallithea" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:30 +msgid "" +"Gravatar url allows you to use other avatar server application.\n" +" Following " +"variables of the URL will be replaced accordingly.\n" +" {scheme} " +"'http' or 'https' sent from running Kallithea server,\n" +" {email} user " +"email,\n" +" {md5email} md5 " +"hash of the user email (like at gravatar.com),\n" +" {size} size " +"of the image that is expected from the server application,\n" +" {netloc} " +"network location/server host of running Kallithea server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:42 msgid "" -"Location where repositories are stored. After changing this value a restart," -" and rescan is required" -msgstr "Local onde os repositórios são armazenados. Depois de mudar este valor uma reinicialização e uma nova varredura são requeridas" - -#: rhodecode/templates/admin/settings/settings.html:303 -msgid "Test Email" -msgstr "Testar E-mail" - -#: rhodecode/templates/admin/settings/settings.html:311 -msgid "Email to" -msgstr "E-mail para" - -#: rhodecode/templates/admin/settings/settings.html:319 -msgid "Send" -msgstr "Enviar" - -#: rhodecode/templates/admin/settings/settings.html:325 -msgid "System Info and Packages" -msgstr "Informações de Sistema e Pacotes" - -#: rhodecode/templates/admin/settings/settings.html:328 -#: rhodecode/templates/changelog/changelog.html:51 -msgid "Show" -msgstr "Mostrar" - -#: rhodecode/templates/admin/users/user_add.html:5 -msgid "Add user" -msgstr "Adicionar usuário" - -#: rhodecode/templates/admin/users/user_add.html:10 -#: rhodecode/templates/admin/users/user_edit.html:11 -#: rhodecode/templates/base/base.html:76 -msgid "Users" -msgstr "Usuários" - -#: rhodecode/templates/admin/users/user_add.html:12 -#: rhodecode/templates/admin/users/users.html:23 -msgid "Add new user" -msgstr "Adicionar novo usuário" - -#: rhodecode/templates/admin/users/user_add.html:50 -msgid "Password confirmation" -msgstr "Confirmação de senha" - -#: rhodecode/templates/admin/users/user_edit.html:5 -msgid "Edit user" -msgstr "Editar usuário" - -#: rhodecode/templates/admin/users/user_edit.html:13 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 -#, python-format -msgid "Edit %s" -msgstr "Editar %s" - -#: rhodecode/templates/admin/users/user_edit.html:34 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:10 -msgid "Change your avatar at" -msgstr "Altere o seu avatar em" - -#: rhodecode/templates/admin/users/user_edit.html:35 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:11 -msgid "Using" -msgstr "Usando" - -#: rhodecode/templates/admin/users/user_edit.html:43 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:20 -msgid "API key" -msgstr "Chave de API" - -#: rhodecode/templates/admin/users/user_edit.html:50 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:25 -msgid "Current IP" -msgstr "IP atual" - -#: rhodecode/templates/admin/users/user_edit.html:70 -msgid "LDAP DN" -msgstr "DN LDAP" - -#: rhodecode/templates/admin/users/user_edit.html:79 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:44 -msgid "New password" -msgstr "Nova senha" - -#: rhodecode/templates/admin/users/user_edit.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:53 -msgid "New password confirmation" -msgstr "Confirmação de nova senha" - -#: rhodecode/templates/admin/users/user_edit.html:163 -msgid "Email addresses" -msgstr "Endereços de email" - -#: rhodecode/templates/admin/users/user_edit.html:176 -#, python-format -msgid "Confirm to delete this email: %s" -msgstr "Confirme para excluir este email: %s" - -#: rhodecode/templates/admin/users/user_edit.html:190 -msgid "New email address" -msgstr "Novo endereço de email" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:5 -#: rhodecode/templates/base/base.html:254 -msgid "My account" -msgstr "Minha conta" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:9 -msgid "My Account" -msgstr "Minha Conta" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:35 -msgid "My permissions" -msgstr "Minhas permissões" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:38 -#: rhodecode/templates/journal/journal.html:54 -msgid "My repos" -msgstr "Meus repositórios" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:41 -msgid "My pull requests" -msgstr "Meus pull requests" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:4 -msgid "Show closed pull requests" -msgstr "Mostrar pull requests fechados" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:6 -msgid "Opened by me" -msgstr "Abertos por mim" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "Pull request $%s aberto em %s" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:17 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:45 -#: rhodecode/templates/pullrequests/pullrequest_data.html:11 -#: rhodecode/templates/pullrequests/pullrequest_show.html:27 -#: rhodecode/templates/pullrequests/pullrequest_show.html:42 -msgid "Closed" -msgstr "Fechado" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:23 -msgid "Confirm to delete this pull request" -msgstr "Confirme para excluir este pull request" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:30 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:51 -msgid "Nothing here yet" -msgstr "Não há nada aqui ainda" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:34 -msgid "I participate in" -msgstr "Eu participo em" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:42 -#: rhodecode/templates/pullrequests/pullrequest_data.html:8 -#, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "Pull request #%s aberto por %s em %s" - -#: rhodecode/templates/admin/users/users.html:5 -msgid "Users administration" -msgstr "Administração de usuários" - -#: rhodecode/templates/admin/users/users.html:9 -msgid "users" -msgstr "usuários" - -#: rhodecode/templates/admin/users/users.html:80 -msgid "Firstname" -msgstr "Primeiro nome" - -#: rhodecode/templates/admin/users/users.html:81 -msgid "Lastname" -msgstr "Último nome" - -#: rhodecode/templates/admin/users/users.html:82 -msgid "Last login" -msgstr "Último login" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:5 +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}'," +" available vars:\n" +" {scheme} 'http' " +"or 'https' sent from running Kallithea server,\n" +" {user} current " +"user username,\n" +" {netloc} network " +"location/server host of running Kallithea server,\n" +" {repo} full " +"repository name,\n" +" {repoid} ID of " +"repository, can be used to contruct clone-by-id" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:54 +msgid "Dashboard items" +msgstr "Itens do dashboard" + +#: kallithea/templates/admin/settings/settings_visual.html:58 +msgid "" +"Number of items displayed in the main page dashboard before pagination is" +" shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:68 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:74 +msgid "Icons" +msgstr "Ícones" + +#: kallithea/templates/admin/settings/settings_visual.html:79 +msgid "Show public repo icon on repositories" +msgstr "Mostrar ícone de repositório público nos repositórios" + +#: kallithea/templates/admin/settings/settings_visual.html:83 +msgid "Show private repo icon on repositories" +msgstr "Mostrar ícone de repositório privado nos repositórios" + +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:91 +msgid "Meta-Tagging" +msgstr "Meta-Tagging" + +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:110 +msgid "" +"Parses meta tags from repository description field and turns them into " +"colored tags." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 msgid "Add user group" msgstr "Adicionar grupo de usuários" -#: rhodecode/templates/admin/users_groups/users_group_add.html:10 -#: rhodecode/templates/admin/users_groups/users_groups.html:11 -#: rhodecode/templates/base/base.html:77 rhodecode/templates/base/base.html:94 +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 msgid "User groups" msgstr "Grupos de usuários" -#: rhodecode/templates/admin/users_groups/users_group_add.html:12 -#: rhodecode/templates/admin/users_groups/users_groups.html:26 -msgid "Add new user group" -msgstr "Adicionar novo grupo de usuários" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 -msgid "Edit user group" -msgstr "Editar grupo de usuários" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 -msgid "UserGroups" -msgstr "Grupos de Usuários" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 -#: rhodecode/templates/admin/users_groups/users_groups.html:38 +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 +#, python-format +msgid "%s user group settings" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "Permissões padrão" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 msgid "Members" msgstr "Membros" -#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 -msgid "Chosen group members" -msgstr "Membros escolhidos do grupo" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 -msgid "Remove all elements" -msgstr "Remover todos os elementos" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 -msgid "Available members" -msgstr "Membros disponíveis" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 -msgid "Add all elements" -msgstr "Adicionar todos os elementos" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:109 -msgid "No members yet" -msgstr "Nenhum membro ainda" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:117 -msgid "Global Permissions" -msgstr "Permissões Globais" - -#: rhodecode/templates/admin/users_groups/users_groups.html:5 -msgid "User groups administration" -msgstr "Administração de grupos de usuários" - -#: rhodecode/templates/admin/users_groups/users_groups.html:55 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 +#, python-format +msgid "User Group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 #, python-format msgid "Confirm to delete this user group: %s" msgstr "Confirme para excluir este grupo de usuário: %s" -#: rhodecode/templates/admin/users_groups/users_groups.html:62 -msgid "There are no user groups yet" -msgstr "Ainda não há um grupo de usuários sequer" - -#: rhodecode/templates/base/base.html:42 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "Nenhum membro ainda" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "Membros escolhidos do grupo" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "Remover todos os elementos" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "Membros disponíveis" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "Adicionar todos os elementos" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "Administração de grupos de usuários" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 +msgid "Add user" +msgstr "Adicionar usuário" + +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 +msgid "Users" +msgstr "Usuários" + +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:53 +msgid "Password confirmation" +msgstr "Confirmação de senha" + +#: kallithea/templates/admin/users/user_edit.html:5 +#, python-format +msgid "%s user settings" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "Confirma excluir este usuário: %s" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 +#, python-format +msgid "" +"This user is in an external Source of Record (%s); some details cannot be" +" managed here." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 +msgid "New password confirmation" +msgstr "Confirmação de nova senha" + +#: kallithea/templates/admin/users/users.html:5 +msgid "Users administration" +msgstr "Administração de usuários" + +#: kallithea/templates/admin/users/users.html:13 +msgid "users" +msgstr "usuários" + +#: kallithea/templates/admin/users/users.html:54 +msgid "Firstname" +msgstr "Primeiro nome" + +#: kallithea/templates/admin/users/users.html:55 +msgid "Lastname" +msgstr "Último nome" + +#: kallithea/templates/admin/users/users.html:56 +msgid "Last login" +msgstr "Último login" + +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "" + +#: kallithea/templates/base/base.html:37 #, python-format msgid "Server instance: %s" msgstr "Instância de servidor: %s" -#: rhodecode/templates/base/base.html:52 -msgid "Report a bug" -msgstr "Relatar um bug" - -#: rhodecode/templates/base/base.html:121 -#: rhodecode/templates/data_table/_dt_elements.html:9 -#: rhodecode/templates/data_table/_dt_elements.html:11 -#: rhodecode/templates/data_table/_dt_elements.html:13 -#: rhodecode/templates/summary/summary.html:8 +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 msgid "Summary" msgstr "Sumário" -#: rhodecode/templates/base/base.html:122 -#: rhodecode/templates/changelog/changelog.html:15 -#: rhodecode/templates/data_table/_dt_elements.html:17 -#: rhodecode/templates/data_table/_dt_elements.html:19 -#: rhodecode/templates/data_table/_dt_elements.html:21 +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 msgid "Changelog" msgstr "Registro de alterações" -#: rhodecode/templates/base/base.html:123 -#: rhodecode/templates/data_table/_dt_elements.html:25 -#: rhodecode/templates/data_table/_dt_elements.html:27 -#: rhodecode/templates/data_table/_dt_elements.html:29 -#: rhodecode/templates/files/files.html:12 +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 msgid "Files" msgstr "Arquivos" -#: rhodecode/templates/base/base.html:125 +#: kallithea/templates/base/base.html:149 msgid "Switch To" msgstr "Trocar Para" -#: rhodecode/templates/base/base.html:127 -#: rhodecode/templates/base/base.html:279 -msgid "loading..." -msgstr "carregando..." - -#: rhodecode/templates/base/base.html:131 +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 msgid "Options" msgstr "Opções" -#: rhodecode/templates/base/base.html:137 -#: rhodecode/templates/forks/forks_data.html:21 +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 msgid "Compare fork" msgstr "Compare bifurcação" -#: rhodecode/templates/base/base.html:139 -#: rhodecode/templates/base/base.html:312 -#: rhodecode/templates/search/search.html:14 -#: rhodecode/templates/search/search.html:54 +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "Compare" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 msgid "Search" msgstr "Pesquisar" -#: rhodecode/templates/base/base.html:145 +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "Destravar" + +#: kallithea/templates/base/base.html:176 msgid "Lock" msgstr "Travar" -#: rhodecode/templates/base/base.html:153 +#: kallithea/templates/base/base.html:184 msgid "Follow" msgstr "Seguir" -#: rhodecode/templates/base/base.html:154 +#: kallithea/templates/base/base.html:185 msgid "Unfollow" msgstr "Parar de seguir" -#: rhodecode/templates/base/base.html:157 -#: rhodecode/templates/data_table/_dt_elements.html:33 -#: rhodecode/templates/data_table/_dt_elements.html:35 -#: rhodecode/templates/data_table/_dt_elements.html:37 -#: rhodecode/templates/data_table/_dt_elements.html:74 -#: rhodecode/templates/forks/fork.html:9 +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 msgid "Fork" msgstr "Bifurcação" -#: rhodecode/templates/base/base.html:159 +#: kallithea/templates/base/base.html:190 msgid "Create Pull Request" msgstr "Criar Pull Request" -#: rhodecode/templates/base/base.html:165 -msgid "Show Pull Requests" -msgstr "Mostrar Pull Requests" - -#: rhodecode/templates/base/base.html:165 -msgid "Pull Requests" -msgstr "Pull Requests" - -#: rhodecode/templates/base/base.html:202 +#: kallithea/templates/base/base.html:196 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "Mostrar Pull Requests para %s" + +#: kallithea/templates/base/base.html:233 msgid "Not logged in" msgstr "Não logado" -#: rhodecode/templates/base/base.html:209 +#: kallithea/templates/base/base.html:240 msgid "Login to your account" msgstr "Entrar com sua conta" -#: rhodecode/templates/base/base.html:232 +#: kallithea/templates/base/base.html:263 msgid "Forgot password ?" msgstr "Esqueceu a senha ?" -#: rhodecode/templates/base/base.html:255 +#: kallithea/templates/base/base.html:286 msgid "Log Out" msgstr "Sair" -#: rhodecode/templates/base/base.html:274 -msgid "Switch repository" -msgstr "Trocar repositório" - -#: rhodecode/templates/base/base.html:286 +#: kallithea/templates/base/base.html:311 msgid "Show recent activity" msgstr "Mostrar atividade recente" -#: rhodecode/templates/base/base.html:287 -#: rhodecode/templates/journal/journal.html:4 +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 msgid "Journal" msgstr "Diário" -#: rhodecode/templates/base/base.html:298 +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "Diário público" + +#: kallithea/templates/base/base.html:323 msgid "Show public gists" msgstr "Mostrar gists públicos" -#: rhodecode/templates/base/base.html:303 +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "Gists" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "Criar novo gist" + +#: kallithea/templates/base/base.html:328 msgid "All public gists" msgstr "Todos os gists públicos" -#: rhodecode/templates/base/base.html:305 +#: kallithea/templates/base/base.html:330 msgid "My public gists" msgstr "Meus gists públicos" -#: rhodecode/templates/base/base.html:306 +#: kallithea/templates/base/base.html:331 msgid "My private gists" msgstr "Meus gists privados" -#: rhodecode/templates/base/base.html:311 +#: kallithea/templates/base/base.html:336 msgid "Search in repositories" msgstr "Buscar nos repositórios" -#: rhodecode/templates/base/default_perms_box.html:14 -msgid "Inherit default permissions" -msgstr "Herdar permissões padrão" - -#: rhodecode/templates/base/default_perms_box.html:18 +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:19 #, python-format msgid "" -"Select to inherit permissions from %s settings. With this selected below " -"options does not apply." -msgstr "Selecione para herdar permissões das configurações de %s. Com isto selecionado as opções abaixo não se aplicam" - -#: rhodecode/templates/base/default_perms_box.html:26 +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:28 msgid "Create repositories" msgstr "Criar repositórios" -#: rhodecode/templates/base/default_perms_box.html:30 +#: kallithea/templates/base/default_perms_box.html:33 msgid "Select this option to allow repository creation for this user" -msgstr "Selecione esta opção para permitir a criação de repositórios para este usuário" - -#: rhodecode/templates/base/default_perms_box.html:35 +msgstr "" +"Selecione esta opção para permitir a criação de repositórios para este " +"usuário" + +#: kallithea/templates/base/default_perms_box.html:40 msgid "Create user groups" msgstr "Criar grupos de usuários" -#: rhodecode/templates/base/default_perms_box.html:39 +#: kallithea/templates/base/default_perms_box.html:45 msgid "Select this option to allow user group creation for this user" -msgstr "Selecione esta opção para permitir a criação de grupos de usuários para este usuário" - -#: rhodecode/templates/base/default_perms_box.html:44 +msgstr "" +"Selecione esta opção para permitir a criação de grupos de usuários para " +"este usuário" + +#: kallithea/templates/base/default_perms_box.html:52 msgid "Fork repositories" msgstr "Bufurcar repositórios" -#: rhodecode/templates/base/default_perms_box.html:48 +#: kallithea/templates/base/default_perms_box.html:57 msgid "Select this option to allow repository forking for this user" -msgstr "Selecione esta opção para permitir a bifurcação de repositórios para este usuário" - -#: rhodecode/templates/base/perms_summary.html:11 +msgstr "" +"Selecione esta opção para permitir a bifurcação de repositórios para este" +" usuário" + +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:22 msgid "No permissions defined yet" msgstr "Nenhuma permissão definida ainda" -#: rhodecode/templates/base/perms_summary.html:19 -#: rhodecode/templates/base/perms_summary.html:38 +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 msgid "Permission" msgstr "Permissão" -#: rhodecode/templates/base/perms_summary.html:20 -#: rhodecode/templates/base/perms_summary.html:39 +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 msgid "Edit Permission" msgstr "Editar Permissão" -#: rhodecode/templates/base/root.html:44 +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 msgid "Add another comment" msgstr "Adicionar outro comentário" -#: rhodecode/templates/base/root.html:45 -#: rhodecode/templates/data_table/_dt_elements.html:147 +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 msgid "Stop following this repository" msgstr "Parar de seguir este repositório" -#: rhodecode/templates/base/root.html:46 +#: kallithea/templates/base/root.html:47 msgid "Start following this repository" msgstr "Passar a seguir este repositório" -#: rhodecode/templates/base/root.html:47 +#: kallithea/templates/base/root.html:48 msgid "Group" msgstr "Grupo" -#: rhodecode/templates/base/root.html:48 +#: kallithea/templates/base/root.html:49 msgid "members" msgstr "membros" -#: rhodecode/templates/base/root.html:49 -#: rhodecode/templates/pullrequests/pullrequest.html:203 +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 msgid "Loading ..." msgstr "Carregando..." -#: rhodecode/templates/base/root.html:50 +#: kallithea/templates/base/root.html:51 +msgid "loading ..." +msgstr "carregando ..." + +#: kallithea/templates/base/root.html:52 msgid "Search truncated" msgstr "Busca truncada" -#: rhodecode/templates/base/root.html:51 +#: kallithea/templates/base/root.html:53 msgid "No matching files" msgstr "Nenhum arquivo encontrado" -#: rhodecode/templates/base/root.html:52 -#: rhodecode/templates/changelog/changelog.html:45 +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 msgid "Open new pull request" msgstr "Crie novo pull request" -#: rhodecode/templates/base/root.html:53 +#: kallithea/templates/base/root.html:55 msgid "Open new pull request for selected changesets" msgstr "Abrir novo pull request para os changesets selecionados" -#: rhodecode/templates/base/root.html:54 +#: kallithea/templates/base/root.html:56 msgid "Show selected changesets __S -> __E" msgstr "Mostrar changesets selecionados __S -> __E" -#: rhodecode/templates/base/root.html:55 +#: kallithea/templates/base/root.html:57 msgid "Show selected changeset __S" msgstr "Mostrar changesets selecionados __S" -#: rhodecode/templates/base/root.html:56 +#: kallithea/templates/base/root.html:58 msgid "Selection link" msgstr "Link da seleção" -#: rhodecode/templates/base/root.html:57 -#: rhodecode/templates/changeset/diff_block.html:8 +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 msgid "Collapse diff" msgstr "Colapsar diff" -#: rhodecode/templates/base/root.html:58 +#: kallithea/templates/base/root.html:60 msgid "Expand diff" msgstr "Expandir diff" -#: rhodecode/templates/base/root.html:59 +#: kallithea/templates/base/root.html:61 msgid "Failed to revoke permission" -msgstr "" - -#: rhodecode/templates/bookmarks/bookmarks.html:5 +msgstr "Falhou ao revocar a permissão" + +#: kallithea/templates/base/root.html:62 +msgid "confirm to revoke permission for {0}: {1} ?" +msgstr "confirme para revogar permissão para {0}: {1} ?" + +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:5 #, python-format msgid "%s Bookmarks" msgstr "%s Bookmarks" -#: rhodecode/templates/bookmarks/bookmarks.html:26 -msgid "Compare bookmarks" -msgstr "Comparar bookmarks" - -#: rhodecode/templates/bookmarks/bookmarks.html:51 -#: rhodecode/templates/bookmarks/bookmarks_data.html:8 -#: rhodecode/templates/branches/branches.html:50 -#: rhodecode/templates/branches/branches_data.html:8 -#: rhodecode/templates/changelog/changelog_summary_data.html:8 -#: rhodecode/templates/tags/tags.html:51 -#: rhodecode/templates/tags/tags_data.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 msgid "Author" msgstr "Autor" -#: rhodecode/templates/bookmarks/bookmarks.html:52 -#: rhodecode/templates/bookmarks/bookmarks_data.html:9 -#: rhodecode/templates/branches/branches.html:51 -#: rhodecode/templates/branches/branches_data.html:9 -#: rhodecode/templates/changelog/changelog_summary_data.html:5 -#: rhodecode/templates/tags/tags.html:52 -#: rhodecode/templates/tags/tags_data.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 msgid "Revision" msgstr "Revisão" -#: rhodecode/templates/bookmarks/bookmarks.html:54 -#: rhodecode/templates/bookmarks/bookmarks_data.html:10 -#: rhodecode/templates/branches/branches.html:53 -#: rhodecode/templates/branches/branches_data.html:10 -#: rhodecode/templates/tags/tags.html:54 -#: rhodecode/templates/tags/tags_data.html:10 -msgid "Compare" -msgstr "Compare" - -#: rhodecode/templates/branches/branches.html:5 +#: kallithea/templates/branches/branches.html:5 #, python-format msgid "%s Branches" msgstr "%s Ramos" -#: rhodecode/templates/branches/branches.html:26 -msgid "Compare branches" -msgstr "Compare ramos" - -#: rhodecode/templates/changelog/changelog.html:6 +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 #, python-format msgid "%s Changelog" msgstr "%s Changelog" -#: rhodecode/templates/changelog/changelog.html:19 +#: kallithea/templates/changelog/changelog.html:21 #, python-format msgid "showing %d out of %d revision" msgid_plural "showing %d out of %d revisions" msgstr[0] "mostrando %d de %d revisão" msgstr[1] "mostrando %d de %d revisões" -#: rhodecode/templates/changelog/changelog.html:39 +#: kallithea/templates/changelog/changelog.html:43 msgid "Clear selection" msgstr "Deselecionar seleção" -#: rhodecode/templates/changelog/changelog.html:42 -#: rhodecode/templates/forks/forks_data.html:19 +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 #, python-format msgid "Compare fork with %s" msgstr "Comparar bifurcação com %s" -#: rhodecode/templates/changelog/changelog.html:42 -msgid "Compare fork with parent" -msgstr "Comparar bifurcação com o pai" - -#: rhodecode/templates/changelog/changelog.html:78 -#: rhodecode/templates/changelog/changelog_summary_data.html:28 -#, python-format -msgid "Click to open associated pull request #%s" -msgstr "Clique para abrir o pull request #%s associado" - -#: rhodecode/templates/changelog/changelog.html:102 -#: rhodecode/templates/summary/summary.html:403 -msgid "Show more" -msgstr "Mostrar mais" - -#: rhodecode/templates/changelog/changelog.html:115 -#: rhodecode/templates/changelog/changelog_summary_data.html:50 -#: rhodecode/templates/changeset/changeset.html:107 -#: rhodecode/templates/changeset/changeset_range.html:86 +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "Mostrar" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 +#, python-format +msgid "" +"Changeset status: %s\n" +"Click to open associated pull request #%s" +msgstr "" +"Estado do changeset: %s\n" +"Clique para abrir os pull request #%s associado" + +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 +#, python-format +msgid "Changeset status: %s" +msgstr "Estado do changeset: %s" + +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:114 +msgid "Changeset has comments" +msgstr "O changeset tem comentários" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 #, python-format msgid "Bookmark %s" msgstr "Bookmark %s" -#: rhodecode/templates/changelog/changelog.html:121 -#: rhodecode/templates/changelog/changelog_summary_data.html:56 -#: rhodecode/templates/changeset/changeset.html:113 -#: rhodecode/templates/changeset/changeset_range.html:92 +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 #, python-format msgid "Tag %s" msgstr "Tag %s" -#: rhodecode/templates/changelog/changelog.html:126 -#: rhodecode/templates/changelog/changelog_summary_data.html:61 -#: rhodecode/templates/changeset/changeset.html:117 -#: rhodecode/templates/changeset/changeset_range.html:96 +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 #, python-format msgid "Branch %s" msgstr "Ramo %s" -#: rhodecode/templates/changelog/changelog.html:286 +#: kallithea/templates/changelog/changelog.html:299 msgid "There are no changes yet" msgstr "Ainda não há alteações" -#: rhodecode/templates/changelog/changelog_details.html:4 -#: rhodecode/templates/changeset/changeset.html:91 +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 msgid "Removed" msgstr "Removido" -#: rhodecode/templates/changelog/changelog_details.html:5 -#: rhodecode/templates/changeset/changeset.html:92 +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 msgid "Changed" msgstr "Modificado" -#: rhodecode/templates/changelog/changelog_details.html:6 -#: rhodecode/templates/changeset/changeset.html:93 +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 msgid "Added" msgstr "Adicionado" -#: rhodecode/templates/changelog/changelog_details.html:8 -#: rhodecode/templates/changelog/changelog_details.html:9 -#: rhodecode/templates/changelog/changelog_details.html:10 -#: rhodecode/templates/changeset/changeset.html:95 -#: rhodecode/templates/changeset/changeset.html:96 -#: rhodecode/templates/changeset/changeset.html:97 +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 #, python-format msgid "Affected %s files" msgstr "Afetados %s arquivos" -#: rhodecode/templates/changelog/changelog_summary_data.html:6 -#: rhodecode/templates/files/files_add.html:75 -#: rhodecode/templates/files/files_edit.html:61 +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 msgid "Commit message" msgstr "Mensagem de commit" -#: rhodecode/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/changelog/changelog_summary_data.html:7 msgid "Age" msgstr "Idade" -#: rhodecode/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/changelog/changelog_summary_data.html:9 msgid "Refs" msgstr "Refs" -#: rhodecode/templates/changelog/changelog_summary_data.html:86 -msgid "Add or upload files directly via RhodeCode" -msgstr "Adicionar ou enviar arquivos diretamente pelo RhodeCode" - -#: rhodecode/templates/changelog/changelog_summary_data.html:89 -#: rhodecode/templates/files/files_add.html:38 -#: rhodecode/templates/files/files_browser.html:31 -msgid "Add new file" -msgstr "Adicionar novo arquivo" - -#: rhodecode/templates/changelog/changelog_summary_data.html:95 +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" +msgstr "Adicionar ou enviar arquivos diretamente pelo Kallithea" + +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:95 msgid "Push new repo" msgstr "Fazer push de novo repositório" -#: rhodecode/templates/changelog/changelog_summary_data.html:103 +#: kallithea/templates/changelog/changelog_summary_data.html:103 msgid "Existing repository?" msgstr "Repositório existente?" -#: rhodecode/templates/changeset/changeset.html:6 +#: kallithea/templates/changeset/changeset.html:6 #, python-format msgid "%s Changeset" msgstr "%s Changeset" -#: rhodecode/templates/changeset/changeset.html:39 -msgid "No parents" -msgstr "Sem progenitores" - -#: rhodecode/templates/changeset/changeset.html:49 -msgid "No children" -msgstr "Nenhum filho" - -#: rhodecode/templates/changeset/changeset.html:62 -#: rhodecode/templates/changeset/changeset_file_comment.html:20 -#: rhodecode/templates/changeset/changeset_range.html:44 +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 msgid "Changeset status" msgstr "Estado do changeset" -#: rhodecode/templates/changeset/changeset.html:67 -#: rhodecode/templates/changeset/diff_block.html:22 +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 msgid "Raw diff" msgstr "Diff cru" -#: rhodecode/templates/changeset/changeset.html:68 +#: kallithea/templates/changeset/changeset.html:58 msgid "Patch diff" msgstr "D" -#: rhodecode/templates/changeset/changeset.html:69 -#: rhodecode/templates/changeset/diff_block.html:23 +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 msgid "Download diff" msgstr "Baixar diff" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "%d comentário" msgstr[1] "%d comentários" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "(%d inline)" msgid_plural "(%d inline)" msgstr[0] "(%d em linha)" msgstr[1] "(%d em linha)" -#: rhodecode/templates/changeset/changeset.html:103 -#: rhodecode/templates/changeset/changeset_range.html:82 +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 msgid "merge" msgstr "mesclar" -#: rhodecode/templates/changeset/changeset.html:126 -#: rhodecode/templates/compare/compare_diff.html:40 -#: rhodecode/templates/pullrequests/pullrequest_show.html:113 +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 #, python-format msgid "%s file changed" msgid_plural "%s files changed" msgstr[0] "%s arquivo modificado" msgstr[1] "%s arquivos modificados" -#: rhodecode/templates/changeset/changeset.html:128 -#: rhodecode/templates/compare/compare_diff.html:42 -#: rhodecode/templates/pullrequests/pullrequest_show.html:115 +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 #, python-format msgid "%s file changed with %s insertions and %s deletions" msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "%s arquivo modificado com %s inserções e %s exclusões" msgstr[1] "%s arquivos modificados com %s inserções e %s exclusões" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Showing a huge diff might take some time and resources" -msgstr "Mostrar um diff muito grande pode levar muito tempo e gastar muitos recursos" - -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +msgstr "" +"Mostrar um diff muito grande pode levar muito tempo e gastar muitos " +"recursos" + +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Show full diff" msgstr "Mostrar diff completo" -#: rhodecode/templates/changeset/changeset_file_comment.html:30 -#, python-format -msgid "Status change on pull request #%s" -msgstr "Mudança de estado no pull request $%s" - -#: rhodecode/templates/changeset/changeset_file_comment.html:32 +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 +#, python-format +msgid "Vote on pull request #%s" +msgstr "Vote no pull request #%s" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 #, python-format msgid "Comment on pull request #%s" msgstr "Comentar no pull request #%s" -#: rhodecode/templates/changeset/changeset_file_comment.html:55 +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Status change on changeset" +msgstr "Alteração de estado no changeset" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Comment on changeset" +msgstr "Comentário no changeset" + +#: kallithea/templates/changeset/changeset_file_comment.html:63 msgid "Submitting..." msgstr "Enviando..." -#: rhodecode/templates/changeset/changeset_file_comment.html:58 +#: kallithea/templates/changeset/changeset_file_comment.html:66 msgid "Commenting on line {1}." msgstr "Comentando a linha {1}." -#: rhodecode/templates/changeset/changeset_file_comment.html:59 -#: rhodecode/templates/changeset/changeset_file_comment.html:145 +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 #, python-format msgid "Comments parsed using %s syntax with %s support." msgstr "Comentários interpretados usando a sintaxe %s com suporte a %s." -#: rhodecode/templates/changeset/changeset_file_comment.html:61 -#: rhodecode/templates/changeset/changeset_file_comment.html:147 -msgid "" -"Use @username inside this text to send notification to this RhodeCode user" -msgstr "Use @nomedeusuário dentro desse texto para enviar notificação a este usuário do RhodeCode" - -#: rhodecode/templates/changeset/changeset_file_comment.html:65 -#: rhodecode/templates/changeset/changeset_file_comment.html:152 +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "" +"Use @nomedeusuário dentro desse texto para enviar notificação a este " +"usuário do Kallithea" + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 msgid "Preview" msgstr "Visualizar" -#: rhodecode/templates/changeset/changeset_file_comment.html:72 -#: rhodecode/templates/changeset/changeset_file_comment.html:170 +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 msgid "Comment preview" msgstr "Visualizar comentário" -#: rhodecode/templates/changeset/changeset_file_comment.html:80 -#: rhodecode/templates/changeset/changeset_file_comment.html:177 -#: rhodecode/templates/email_templates/changeset_comment.html:16 -#: rhodecode/templates/email_templates/pull_request_comment.html:16 +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 msgid "Comment" msgstr "Comentário" -#: rhodecode/templates/changeset/changeset_file_comment.html:81 -msgid "Cancel" -msgstr "Cancelar" - -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "You need to be logged in to comment." msgstr "Você precisa estar logado para comentar." -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "Login now" msgstr "Entrar agora" -#: rhodecode/templates/changeset/changeset_file_comment.html:92 +#: kallithea/templates/changeset/changeset_file_comment.html:100 msgid "Hide" msgstr "Ocultar" -#: rhodecode/templates/changeset/changeset_file_comment.html:149 -msgid "Change status" -msgstr "Mudar estado" - -#: rhodecode/templates/changeset/changeset_file_comment.html:179 -msgid "Comment and close" -msgstr "Comentar e fechar" - -#: rhodecode/templates/changeset/changeset_range.html:5 +#: kallithea/templates/changeset/changeset_file_comment.html:159 +msgid "Vote for pull request status" +msgstr "Vote para estado do pull request" + +#: kallithea/templates/changeset/changeset_file_comment.html:161 +msgid "Change changeset status" +msgstr "Altere o estado do changeset" + +#: kallithea/templates/changeset/changeset_file_comment.html:179 +msgid "Close (when approved or rejected)" +msgstr "Fechar (quando aprovado ou rejeitado)" + +#: kallithea/templates/changeset/changeset_range.html:5 #, python-format msgid "%s Changesets" msgstr "%s Changesets" -#: rhodecode/templates/changeset/changeset_range.html:52 +#: kallithea/templates/changeset/changeset_range.html:59 msgid "Files affected" msgstr "Arquivos afetados" -#: rhodecode/templates/changeset/diff_block.html:21 +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 msgid "Show full diff for this file" msgstr "Mostrar diff completo para este arquivo" -#: rhodecode/templates/changeset/diff_block.html:29 +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Show full side-by-side diff for this file" +msgstr "Mostrar diff completo lado-a-lado para este arquivo" + +#: kallithea/templates/changeset/diff_block.html:38 msgid "Show inline comments" msgstr "Mostrar comentários inline" -#: rhodecode/templates/changeset/diff_block.html:53 +#: kallithea/templates/changeset/diff_block.html:62 msgid "Show file at latest version in this repo" msgstr "Mostrar última versão do arquivo neste repo" -#: rhodecode/templates/changeset/diff_block.html:54 +#: kallithea/templates/changeset/diff_block.html:64 msgid "Show file at initial version in this repo" msgstr "Mostrar versão inicial do arquivo neste repo" -#: rhodecode/templates/compare/compare_cs.html:4 +#: kallithea/templates/compare/compare_cs.html:4 msgid "No changesets" msgstr "Nenhum changeset" -#: rhodecode/templates/compare/compare_cs.html:32 +#: kallithea/templates/compare/compare_cs.html:8 msgid "Ancestor" msgstr "Antecessor" -#: rhodecode/templates/compare/compare_diff.html:5 +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 #, python-format msgid "%s Compare" msgstr "%s Comparar" -#: rhodecode/templates/compare/compare_diff.html:9 +#: kallithea/templates/compare/compare_diff.html:16 msgid "Compare revisions" msgstr "Comparar revisões" -#: rhodecode/templates/compare/compare_diff.html:33 -#: rhodecode/templates/pullrequests/pullrequest_show.html:106 +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 #, python-format msgid "Showing %s commit" msgid_plural "Showing %s commits" msgstr[0] "Mostrando %s commit" msgstr[1] "Mostrando %s commits" -#: rhodecode/templates/compare/compare_diff.html:48 -#: rhodecode/templates/pullrequests/pullrequest_show.html:121 +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 msgid "No files" msgstr "Nenhum arquivo" -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -msgid "confirm to show potentially huge diff" -msgstr "confirme para mostrar diff potencialmente muito grande" - -#: rhodecode/templates/data_table/_dt_elements.html:54 -#: rhodecode/templates/summary/summary.html:69 +#: kallithea/templates/data_table/_dt_elements.html:63 msgid "Mercurial repository" msgstr "Repositório Mercurial" -#: rhodecode/templates/data_table/_dt_elements.html:56 -#: rhodecode/templates/summary/summary.html:72 +#: kallithea/templates/data_table/_dt_elements.html:65 msgid "Git repository" msgstr "Repositório Git" -#: rhodecode/templates/data_table/_dt_elements.html:74 -#, python-format -msgid "Fork of %s" -msgstr "Bifurcação de %s" - -#: rhodecode/templates/data_table/_dt_elements.html:88 +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "Repositório público" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:96 msgid "No changesets yet" msgstr "Nenhum conjunto de alterações ainda." -#: rhodecode/templates/data_table/_dt_elements.html:95 -#: rhodecode/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 #, python-format msgid "Subscribe to %s rss feed" msgstr "Assinar o feed rss de %s" -#: rhodecode/templates/data_table/_dt_elements.html:103 -#: rhodecode/templates/data_table/_dt_elements.html:105 +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 #, python-format msgid "Subscribe to %s atom feed" msgstr "Assinar o feed atom de %s" -#: rhodecode/templates/data_table/_dt_elements.html:122 -#, python-format -msgid "Confirm to delete this repository: %s" -msgstr "Confirma excluir esse repositório: %s" - -#: rhodecode/templates/data_table/_dt_elements.html:137 -#, python-format -msgid "Confirm to delete this user: %s" -msgstr "Confirma excluir este usuário: %s" - -#: rhodecode/templates/email_templates/changeset_comment.html:4 -#: rhodecode/templates/email_templates/pull_request.html:4 -#: rhodecode/templates/email_templates/pull_request_comment.html:4 -msgid "URL" -msgstr "URL" - -#: rhodecode/templates/email_templates/changeset_comment.html:6 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:6 #, python-format msgid "%s commented on a %s changeset." msgstr "%s comentou num changeset de %s." -#: rhodecode/templates/email_templates/changeset_comment.html:14 +#: kallithea/templates/email_templates/changeset_comment.html:9 msgid "The changeset status was changed to" msgstr "O estado do changeset foi alterado para" -#: rhodecode/templates/email_templates/main.html:8 -msgid "This is a notification from RhodeCode." -msgstr "Esta é uma notificação do RhodeCode." - -#: rhodecode/templates/email_templates/password_reset.html:4 +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." +msgstr "Esta é uma notificação do Kallithea." + +#: kallithea/templates/email_templates/password_reset.html:4 #, python-format msgid "Hello %s" msgstr "Olá %s" -#: rhodecode/templates/email_templates/password_reset.html:5 +#: kallithea/templates/email_templates/password_reset.html:5 msgid "We received a request to create a new password for your account." msgstr "Recebemos uma requisição para criar uma nova senha para sua conta." -#: rhodecode/templates/email_templates/password_reset.html:6 +#: kallithea/templates/email_templates/password_reset.html:6 msgid "You can generate it by clicking following URL" msgstr "Você pode gerá-la clicando na seguinte URL" -#: rhodecode/templates/email_templates/password_reset.html:10 +#: kallithea/templates/email_templates/password_reset.html:10 msgid "Please ignore this email if you did not request a new password ." msgstr "Por favor, ignore este email se você não requisitou uma nova senha." -#: rhodecode/templates/email_templates/pull_request.html:6 +#: kallithea/templates/email_templates/pull_request.html:6 #, python-format msgid "" -"%s opened a pull request for repository %s and wants you to review changes." +"%s opened a pull request for repository %s and wants you to review " +"changes." msgstr "%s abriu um pull request para o repositório %s e espera sua revisão." -#: rhodecode/templates/email_templates/pull_request.html:8 -#: rhodecode/templates/pullrequests/pullrequest.html:34 -#: rhodecode/templates/pullrequests/pullrequest_data.html:14 -#: rhodecode/templates/pullrequests/pullrequest_show.html:25 +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 msgid "Title" msgstr "Título" -#: rhodecode/templates/email_templates/pull_request_comment.html:6 +#: kallithea/templates/email_templates/pull_request_comment.html:6 #, python-format msgid "%s commented on pull request \"%s\"" msgstr "%s comentou no pull request \"%s\"" -#: rhodecode/templates/email_templates/pull_request_comment.html:10 +#: kallithea/templates/email_templates/pull_request_comment.html:10 msgid "Pull request was closed with status" msgstr "O pull request foi fechado com o estado" -#: rhodecode/templates/email_templates/pull_request_comment.html:12 +#: kallithea/templates/email_templates/pull_request_comment.html:12 msgid "Pull request changed status" msgstr "O pull request mudou de estado" -#: rhodecode/templates/email_templates/registration.html:6 +#: kallithea/templates/email_templates/registration.html:6 msgid "View this user here" msgstr "Veja este usuário aqui" -#: rhodecode/templates/errors/error_document.html:55 +#: kallithea/templates/errors/error_document.html:47 #, python-format msgid "You will be redirected to %s in %s seconds" msgstr "Você será redirecionado para %s em %s segundos" -#: rhodecode/templates/files/file_diff.html:4 +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "Arquivo %s diff lado-a-lado" + +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 +msgid "File diff" +msgstr "Diff do arquivo" + +#: kallithea/templates/files/diff_2way.html:58 +msgid "ignore white space" +msgstr "ignorar espaços em branco" + +#: kallithea/templates/files/diff_2way.html:59 +msgid "turn on edit mode" +msgstr "habilitar modo de edição" + +#: kallithea/templates/files/file_diff.html:4 #, python-format msgid "%s File Diff" msgstr "%s Diff de Arquivo" -#: rhodecode/templates/files/file_diff.html:8 -msgid "File diff" -msgstr "Diff do arquivo" - -#: rhodecode/templates/files/files.html:4 -#: rhodecode/templates/files/files.html:76 +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 #, python-format msgid "%s Files" msgstr "%s Arquivos" -#: rhodecode/templates/files/files.html:30 -#: rhodecode/templates/files/files_add.html:31 -#: rhodecode/templates/files/files_edit.html:31 -msgid "Branch" -msgstr "Ramo" - -#: rhodecode/templates/files/files_add.html:4 +#: kallithea/templates/files/files_add.html:4 #, python-format msgid "%s Files Add" msgstr "%s Adicionar Arquivos" -#: rhodecode/templates/files/files_add.html:19 -msgid "Add file" -msgstr "Adicionar arquivo" - -#: rhodecode/templates/files/files_add.html:43 -msgid "File Name" -msgstr "Nome de Arquivo" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:56 -msgid "or" -msgstr "ou" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:52 -msgid "Upload file" -msgstr "Enviar arquivo" - -#: rhodecode/templates/files/files_add.html:56 -msgid "Create new file" -msgstr "Criar novo arquivo" - -#: rhodecode/templates/files/files_add.html:61 -#: rhodecode/templates/files/files_edit.html:37 -#: rhodecode/templates/files/files_ypjax.html:3 +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" +msgstr "Adicionar novo arquivo" + +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 msgid "Location" msgstr "Local" -#: rhodecode/templates/files/files_add.html:65 -msgid "use / to separate directories" -msgstr "use / para separar diretórios" - -#: rhodecode/templates/files/files_add.html:79 -#: rhodecode/templates/files/files_edit.html:65 +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 +msgid "or" +msgstr "ou" + +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:58 +msgid "New file mode" +msgstr "" + +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 msgid "Commit changes" msgstr "Realizar commit das alterações" -#: rhodecode/templates/files/files_browser.html:13 -msgid "View" -msgstr "Visualizar" - -#: rhodecode/templates/files/files_browser.html:14 +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:14 msgid "Previous revision" msgstr "Revisão anterior" -#: rhodecode/templates/files/files_browser.html:16 +#: kallithea/templates/files/files_browser.html:16 msgid "Next revision" msgstr "Próxima revisão" -#: rhodecode/templates/files/files_browser.html:23 +#: kallithea/templates/files/files_browser.html:22 msgid "Follow current branch" msgstr "Seguir o ramo atual" -#: rhodecode/templates/files/files_browser.html:27 -msgid "Search file list" -msgstr "Buscar a lista de arquivos" - -#: rhodecode/templates/files/files_browser.html:35 +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:29 msgid "Loading file list..." msgstr "Carregando lista de arquivos..." -#: rhodecode/templates/files/files_browser.html:48 +#: kallithea/templates/files/files_browser.html:42 msgid "Size" msgstr "Tamanho" -#: rhodecode/templates/files/files_browser.html:49 +#: kallithea/templates/files/files_browser.html:43 msgid "Mimetype" msgstr "Mimetype" -#: rhodecode/templates/files/files_browser.html:50 +#: kallithea/templates/files/files_browser.html:44 msgid "Last Revision" msgstr "Última revisão" -#: rhodecode/templates/files/files_browser.html:51 +#: kallithea/templates/files/files_browser.html:45 msgid "Last modified" msgstr "Última alteração" -#: rhodecode/templates/files/files_browser.html:52 +#: kallithea/templates/files/files_browser.html:46 msgid "Last committer" msgstr "Último commiter" -#: rhodecode/templates/files/files_edit.html:4 -#, python-format -msgid "%s Files Edit" -msgstr "%s Editar Arquivos" - -#: rhodecode/templates/files/files_edit.html:19 +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:25 msgid "Edit file" msgstr "Editar arquivo" -#: rhodecode/templates/files/files_edit.html:47 -#: rhodecode/templates/files/files_source.html:23 -msgid "Show annotation" -msgstr "Mostrar anotação" - -#: rhodecode/templates/files/files_edit.html:49 -#: rhodecode/templates/files/files_source.html:26 -msgid "Download as raw" -msgstr "Baixar original" - -#: rhodecode/templates/files/files_edit.html:52 +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:58 msgid "Source" msgstr "Fonte" -#: rhodecode/templates/files/files_edit.html:57 +#: kallithea/templates/files/files_edit.html:63 msgid "Editing file" msgstr "Editando arquivo" -#: rhodecode/templates/files/files_history_box.html:2 -msgid "History" -msgstr "Histórico" - -#: rhodecode/templates/files/files_history_box.html:9 -msgid "Diff to revision" -msgstr "Diff para revisão" - -#: rhodecode/templates/files/files_history_box.html:10 -msgid "Show at revision" -msgstr "Mostrar na revisão" - -#: rhodecode/templates/files/files_history_box.html:11 -msgid "Show full history" -msgstr "Mostrar história completa" - -#: rhodecode/templates/files/files_history_box.html:16 +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 #, python-format msgid "%s author" msgid_plural "%s authors" msgstr[0] "%s autor" msgstr[1] "%s autores" -#: rhodecode/templates/files/files_source.html:6 -msgid "Load file history" -msgstr "Carregar história do arquivo" - -#: rhodecode/templates/files/files_source.html:21 -msgid "Show source" -msgstr "Mostrar fonte" - -#: rhodecode/templates/files/files_source.html:29 -#, python-format -msgid "Edit on branch:%s" -msgstr "Editar no ramo:%s" - -#: rhodecode/templates/files/files_source.html:31 -msgid "Edit on branch:?" -msgstr "Editar no ramo:?" - -#: rhodecode/templates/files/files_source.html:31 +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:8 +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:11 +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" +msgstr "" + +#: kallithea/templates/files/files_source.html:38 +#, python-format +msgid "Edit on Branch:%s" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "" + +#: kallithea/templates/files/files_source.html:44 msgid "Editing files allowed only when on branch head revision" -msgstr "A edição de arquivos só é permitida quando se está na revisão mais recente do ramo" - -#: rhodecode/templates/files/files_source.html:46 +msgstr "" +"A edição de arquivos só é permitida quando se está na revisão mais " +"recente do ramo" + +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:61 #, python-format msgid "Binary file (%s)" msgstr "Arquivo binário (%s)" -#: rhodecode/templates/files/files_source.html:55 +#: kallithea/templates/files/files_source.html:71 msgid "File is too big to display" msgstr "Arquivo é grande demais para exibir" -#: rhodecode/templates/files/files_ypjax.html:5 +#: kallithea/templates/files/files_ypjax.html:5 msgid "annotation" msgstr "anotação" -#: rhodecode/templates/files/files_ypjax.html:15 -msgid "Go back" -msgstr "Voltar" - -#: rhodecode/templates/files/files_ypjax.html:16 +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:24 msgid "No files at given path" msgstr "Nenhum arquivo no caminho especificado" -#: rhodecode/templates/followers/followers.html:5 +#: kallithea/templates/followers/followers.html:5 #, python-format msgid "%s Followers" msgstr "%s Seguidores" -#: rhodecode/templates/followers/followers.html:9 -#: rhodecode/templates/summary/summary.html:183 -#: rhodecode/templates/summary/summary.html:184 +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 msgid "Followers" msgstr "Seguidores" -#: rhodecode/templates/followers/followers_data.html:12 +#: kallithea/templates/followers/followers_data.html:12 msgid "Started following -" msgstr "Começou a seguir -" -#: rhodecode/templates/forks/fork.html:5 -#, python-format -msgid "%s Fork" -msgstr "%s Bifurcação" - -#: rhodecode/templates/forks/fork.html:28 +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:30 msgid "Fork name" msgstr "Nome da bifurcação" -#: rhodecode/templates/forks/fork.html:65 +#: kallithea/templates/forks/fork.html:71 msgid "Private" msgstr "Privado" -#: rhodecode/templates/forks/fork.html:74 +#: kallithea/templates/forks/fork.html:80 msgid "Copy permissions" msgstr "Copiar permissões" -#: rhodecode/templates/forks/fork.html:78 +#: kallithea/templates/forks/fork.html:84 msgid "Copy permissions from forked repository" msgstr "Copiar permissões do repositório bifurcado" -#: rhodecode/templates/forks/fork.html:84 +#: kallithea/templates/forks/fork.html:90 msgid "Update after clone" msgstr "Atualizar após clonar" -#: rhodecode/templates/forks/fork.html:88 +#: kallithea/templates/forks/fork.html:94 msgid "Checkout source after making a clone" msgstr "Checkout fontes depois de criar o clone" -#: rhodecode/templates/forks/fork.html:93 -msgid "Fork this repository" -msgstr "Bifurcar este repositório" - -#: rhodecode/templates/forks/forks.html:5 +#: kallithea/templates/forks/fork.html:99 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 #, python-format msgid "%s Forks" msgstr "%s Bifurcações" -#: rhodecode/templates/forks/forks.html:9 -#: rhodecode/templates/summary/summary.html:189 -#: rhodecode/templates/summary/summary.html:190 +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 msgid "Forks" msgstr "Bifurcações" -#: rhodecode/templates/forks/forks_data.html:17 +#: kallithea/templates/forks/forks_data.html:17 msgid "Forked" msgstr "Bifurcado" -#: rhodecode/templates/forks/forks_data.html:42 +#: kallithea/templates/forks/forks_data.html:42 msgid "There are no forks yet" msgstr "Ainda não há bifurcações" -#: rhodecode/templates/journal/journal.html:21 +#: kallithea/templates/journal/journal.html:24 msgid "ATOM journal feed" msgstr "ATOM feed do diário" -#: rhodecode/templates/journal/journal.html:22 +#: kallithea/templates/journal/journal.html:25 msgid "RSS journal feed" msgstr "RSS feed do diário" -#: rhodecode/templates/journal/journal.html:32 -msgid "Refresh" -msgstr "Atualizar" - -#: rhodecode/templates/journal/journal.html:35 -#: rhodecode/templates/journal/public_journal.html:24 -msgid "ATOM feed" -msgstr "ATOM feed" - -#: rhodecode/templates/journal/journal.html:51 -msgid "Watched" -msgstr "Seguindo" - -#: rhodecode/templates/journal/journal_data.html:55 +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "Meus repositórios" + +#: kallithea/templates/journal/journal_data.html:55 msgid "No entries yet" msgstr "Ainda não há entradas" -#: rhodecode/templates/journal/public_journal.html:4 -#: rhodecode/templates/journal/public_journal.html:21 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 msgid "Public Journal" msgstr "Diário Público" -#: rhodecode/templates/journal/public_journal.html:13 +#: kallithea/templates/journal/public_journal.html:16 msgid "ATOM public journal feed" msgstr "ATOM feed do diário público" -#: rhodecode/templates/journal/public_journal.html:14 +#: kallithea/templates/journal/public_journal.html:17 msgid "RSS public journal feed" msgstr "RSS feed do diário público" -#: rhodecode/templates/pullrequests/pullrequest.html:4 -#: rhodecode/templates/pullrequests/pullrequest.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 msgid "New pull request" msgstr "Novo pull request" -#: rhodecode/templates/pullrequests/pullrequest.html:25 -msgid "Create new pull request" -msgstr "Criar novo pull request" - -#: rhodecode/templates/pullrequests/pullrequest.html:47 +#: kallithea/templates/pullrequests/pullrequest.html:44 msgid "Write a short description on this pull request" msgstr "Escreva uma breve descrição para este pull request" -#: rhodecode/templates/pullrequests/pullrequest.html:53 +#: kallithea/templates/pullrequests/pullrequest.html:50 msgid "Changeset flow" msgstr "Fluxo de changesets" -#: rhodecode/templates/pullrequests/pullrequest.html:60 -#: rhodecode/templates/pullrequests/pullrequest_show.html:65 +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 msgid "Origin repository" msgstr "Repositório origem" -#: rhodecode/templates/pullrequests/pullrequest.html:85 -msgid "Send pull request" -msgstr "Enviar pull request" - -#: rhodecode/templates/pullrequests/pullrequest.html:94 -#: rhodecode/templates/pullrequests/pullrequest_show.html:137 +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 msgid "Pull request reviewers" msgstr "Revisores do pull request" -#: rhodecode/templates/pullrequests/pullrequest.html:103 -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 msgid "owner" msgstr "dono" -#: rhodecode/templates/pullrequests/pullrequest.html:115 +#: kallithea/templates/pullrequests/pullrequest.html:114 msgid "Add reviewer to this pull request." msgstr "Adicionar revisor a este pull request" -#: rhodecode/templates/pullrequests/pullrequest.html:129 +#: kallithea/templates/pullrequests/pullrequest.html:128 msgid "Detailed compare view" msgstr "Visão de comparação detalhada" -#: rhodecode/templates/pullrequests/pullrequest.html:150 +#: kallithea/templates/pullrequests/pullrequest.html:149 msgid "Destination repository" msgstr "Repositório de destino" -#: rhodecode/templates/pullrequests/pullrequest_show.html:4 +#: kallithea/templates/pullrequests/pullrequest_show.html:4 #, python-format msgid "%s Pull Request #%s" msgstr "%s Pull Request #%s" -#: rhodecode/templates/pullrequests/pullrequest_show.html:35 +#: kallithea/templates/pullrequests/pullrequest_show.html:36 msgid "Review status" msgstr "Estado da revisão" -#: rhodecode/templates/pullrequests/pullrequest_show.html:40 -msgid "Pull request status" -msgstr "Estado do pull request" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 +msgid "Pull request status calculated from votes" +msgstr "Estado do pull request calculado a partir dos votos" + +#: kallithea/templates/pullrequests/pullrequest_show.html:56 msgid "Still not reviewed by" msgstr "Ainda não revisado por" -#: rhodecode/templates/pullrequests/pullrequest_show.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:60 #, python-format msgid "%d reviewer" msgid_plural "%d reviewers" -msgstr[0] "" -msgstr[1] "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:59 +msgstr[0] "%d revisor" +msgstr[1] "%d revisores" + +#: kallithea/templates/pullrequests/pullrequest_show.html:62 msgid "Pull request was reviewed by all reviewers" msgstr "O pull request foi revisado por todos os revisores" -#: rhodecode/templates/pullrequests/pullrequest_show.html:89 -msgid "Created on" -msgstr "Criado em" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:102 +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 +msgid "Pull changes" +msgstr "Puxar mudanças" + +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "reviewer" +msgstr "revisor" + +#: kallithea/templates/pullrequests/pullrequest_show.html:133 +msgid "Add or remove reviewer to this pull request." +msgstr "Adicionar ou remover revisor a este pull request" + +#: kallithea/templates/pullrequests/pullrequest_show.html:137 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 msgid "Compare view" msgstr "Visão de comparação" -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 -msgid "reviewer" -msgstr "revisor" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:164 -msgid "Add or remove reviewer to this pull request." -msgstr "Adicionar ou remover revisor a este pull request" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:168 -msgid "Save changes" -msgstr "Salvar modificações" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:4 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 #, python-format msgid "%s Pull Requests" -msgstr "" - -#: rhodecode/templates/search/search.html:6 -msgid "Search repository" -msgstr "Buscar no repositório" - -#: rhodecode/templates/search/search.html:8 -#: rhodecode/templates/search/search.html:16 +msgstr "%s Pull Requests" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 +#, python-format +msgid "Pull requests from %s" +msgstr "Pull requests de %s" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 +#, python-format +msgid "Pull requests to %s" +msgstr "Pull requests para %s" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 +msgid "Hide closed pull requests" +msgstr "Esconder pull requests fechados" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 +msgid "Show closed pull requests too" +msgstr "Mostrar pull requests fechados também" + +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 msgid "Search in all repositories" msgstr "Buscar em todos os repositórios" -#: rhodecode/templates/search/search.html:50 +#: kallithea/templates/search/search.html:53 msgid "Search term" msgstr "Termo de pesquisa" -#: rhodecode/templates/search/search.html:62 +#: kallithea/templates/search/search.html:65 msgid "Search in" msgstr "Pesquisando em" -#: rhodecode/templates/search/search.html:65 +#: kallithea/templates/search/search.html:68 msgid "File contents" msgstr "Conteúdo dos arquivos" -#: rhodecode/templates/search/search.html:66 +#: kallithea/templates/search/search.html:69 msgid "Commit messages" msgstr "Mensagens de commit" -#: rhodecode/templates/search/search.html:67 +#: kallithea/templates/search/search.html:70 msgid "File names" msgstr "Nomes dos arquivos" -#: rhodecode/templates/search/search_commit.html:35 -#: rhodecode/templates/search/search_content.html:21 -#: rhodecode/templates/search/search_path.html:15 +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 msgid "Permission denied" msgstr "Permissão negada" -#: rhodecode/templates/summary/summary.html:4 +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 +#, python-format +msgid "%s ATOM feed" +msgstr "%s ATOM feed" + +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 +#, python-format +msgid "%s RSS feed" +msgstr "%s RSS feed" + +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "Habilitar" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "Estatísticas coletadas:" + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "arquivos" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "Mostrar mais" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "commits" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "arquivos adicionados" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "arquivos alterados" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "arquivos removidos" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "commit" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "arquivo adicionado" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "arquivo alterado" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "arquivo removido" + +#: kallithea/templates/summary/summary.html:4 #, python-format msgid "%s Summary" msgstr "%s Sumário" -#: rhodecode/templates/summary/summary.html:16 -#, python-format -msgid "%s ATOM feed" -msgstr "%s ATOM feed" - -#: rhodecode/templates/summary/summary.html:17 -#, python-format -msgid "%s RSS feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:62 +#: kallithea/templates/summary/summary.html:16 #, python-format msgid "Repository locked by %s" msgstr "Repositório travado por %s" -#: rhodecode/templates/summary/summary.html:64 +#: kallithea/templates/summary/summary.html:18 msgid "Repository unlocked" msgstr "Repositório destravado" -#: rhodecode/templates/summary/summary.html:83 -#, python-format -msgid "Non changable ID %s" -msgstr "ID não alterável %s" - -#: rhodecode/templates/summary/summary.html:88 -msgid "Public" -msgstr "Público" - -#: rhodecode/templates/summary/summary.html:88 -#: rhodecode/templates/summary/summary.html:89 -msgid "Fork of" -msgstr "Bifurcação de" - -#: rhodecode/templates/summary/summary.html:97 -msgid "Remote clone" -msgstr "Clone remoto" - -#: rhodecode/templates/summary/summary.html:117 -msgid "Contact" -msgstr "Contato" - -#: rhodecode/templates/summary/summary.html:131 +#: kallithea/templates/summary/summary.html:76 msgid "Clone url" msgstr "URL de clonagem" -#: rhodecode/templates/summary/summary.html:136 +#: kallithea/templates/summary/summary.html:81 msgid "Show by Name" msgstr "Mostrar por Nome" -#: rhodecode/templates/summary/summary.html:137 +#: kallithea/templates/summary/summary.html:82 msgid "Show by ID" msgstr "Mostrar por ID" -#: rhodecode/templates/summary/summary.html:143 +#: kallithea/templates/summary/summary.html:99 msgid "Trending files" msgstr "Tendências em arquivos" -#: rhodecode/templates/summary/summary.html:151 -#: rhodecode/templates/summary/summary.html:167 -msgid "Enable" -msgstr "Habilitar" - -#: rhodecode/templates/summary/summary.html:159 +#: kallithea/templates/summary/summary.html:115 msgid "Download" msgstr "Download" -#: rhodecode/templates/summary/summary.html:163 +#: kallithea/templates/summary/summary.html:119 msgid "There are no downloads yet" msgstr "Ainda não há downloads" -#: rhodecode/templates/summary/summary.html:165 +#: kallithea/templates/summary/summary.html:121 msgid "Downloads are disabled for this repository" msgstr "Downloads estão desabilitados para este repositório" -#: rhodecode/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:127 msgid "Download as zip" msgstr "Download como zip" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "Check this to download archive with subrepos" msgstr "Marque isto para descarregar arquivo com subrepositórios" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "with subrepos" msgstr "com subrepositórios" -#: rhodecode/templates/summary/summary.html:197 +#: kallithea/templates/summary/summary.html:163 msgid "Repository Size" msgstr "Tamanho do Repositório" -#: rhodecode/templates/summary/summary.html:204 -#: rhodecode/templates/summary/summary.html:206 +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 msgid "Feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:224 -msgid "Commit activity by day / author" -msgstr "Atividade de commit por dia / autor" - -#: rhodecode/templates/summary/summary.html:232 -msgid "enable" -msgstr "habilitar" - -#: rhodecode/templates/summary/summary.html:235 -msgid "Stats gathered: " -msgstr "Estatísticas coletadas:" - -#: rhodecode/templates/summary/summary.html:256 +msgstr "Feed" + +#: kallithea/templates/summary/summary.html:193 msgid "Latest changes" msgstr "Mudanças mais recentes" -#: rhodecode/templates/summary/summary.html:258 +#: kallithea/templates/summary/summary.html:195 msgid "Quick start" msgstr "Início rápido" -#: rhodecode/templates/summary/summary.html:272 -#, python-format -msgid "Readme file from revision %s" -msgstr "Arquivo README da revisão %s" - -#: rhodecode/templates/summary/summary.html:332 +#: kallithea/templates/summary/summary.html:209 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:299 #, python-format msgid "Download %s as %s" msgstr "Descarregar %s como %s" -#: rhodecode/templates/summary/summary.html:379 -msgid "files" -msgstr "arquivos" - -#: rhodecode/templates/summary/summary.html:689 -msgid "commits" -msgstr "commits" - -#: rhodecode/templates/summary/summary.html:690 -msgid "files added" -msgstr "arquivos adicionados" - -#: rhodecode/templates/summary/summary.html:691 -msgid "files changed" -msgstr "arquivos alterados" - -#: rhodecode/templates/summary/summary.html:692 -msgid "files removed" -msgstr "arquivos removidos" - -#: rhodecode/templates/summary/summary.html:694 -msgid "commit" -msgstr "commit" - -#: rhodecode/templates/summary/summary.html:695 -msgid "file added" -msgstr "arquivo adicionado" - -#: rhodecode/templates/summary/summary.html:696 -msgid "file changed" -msgstr "arquivo alterado" - -#: rhodecode/templates/summary/summary.html:697 -msgid "file removed" -msgstr "arquivo removido" - -#: rhodecode/templates/tags/tags.html:5 +#: kallithea/templates/tags/tags.html:5 #, python-format msgid "%s Tags" msgstr "%s Tags" -#: rhodecode/templates/tags/tags.html:26 +#: kallithea/templates/tags/tags.html:29 msgid "Compare tags" msgstr "Comparar tags" + diff --git a/rhodecode/i18n/ru/LC_MESSAGES/rhodecode.mo b/kallithea/i18n/ru/LC_MESSAGES/kallithea.mo rename from rhodecode/i18n/ru/LC_MESSAGES/rhodecode.mo rename to kallithea/i18n/ru/LC_MESSAGES/kallithea.mo index d76c0b0ed673d6774cfc1b00522d402592abf34b..4d22834ec4ac93cd2f31f72e4813e905eb37a3b9 GIT binary patch literal 101129 zc%0%P0-53t=d+t)w(aOw*TjOzR$V$+&gzd#J=zE{e1qm}DO$2)o{1d?< zg5MYlcrrn*qLSb_1Q!xKgy0hdzeVsRf(He*i5y1o`@@hvXc+QU z5bRDcJ`DY6P&kL+H@QFhe67Nt5d2SqEn2Q^7~222zW;;5w+S9j@b3h_LGYmANdF$e z{Rtkg&jW|!{Rn~w5-b~ze#M5P{YHY{BRFq3@VAcOz65s+M?W4Pj(+@_;64OjCiou& zU)T5V499psCwMf$Z;t@}`i}r!%15BxYJv{InFMPI-Z%pF?KLtI8AWhEg4Yq8JQCx5 zPvJL8(chy99!juZDaJEW)6XNgH_ulo`c+$sdefyCN0a8CNATN>?^4XuOyuRk};UC?~cWI zHxfLb;9~^)@O+J1WzbKxhTQD1eX)+$@5YM ze7sVI@_U^ZiJZuEa31nkorm>&<#{N#<2&-Q&^k_2V(l zpDFwU!6OKMq4^FgN4aClK~F==f#0#^!2i^8&}FV1bhCnBZ^le*2aJpZ;F^ZRBw z*4;nL(SG*|wDa8xq#sv-cKQ+Ai`Q=j>K&x%!!>_d1=iR31dn5S(e%|7po1H<+!lqq zDlm@63HIlHQ~)pEodEhgcLMq|egei*H38$CH392(*#zL{-U*<~C$-#56VR_ePXHah ztIzvRMEL_J0#7|AVm+Kb5$%kb2z*>b@GOE^f~7nk6M?_aCxY+voJ2f?@i7VOX5l3C z@4-nJ_s=I`eZDhE`LRA9I2rgqb~5sxH5vVzNRXIqG~}ALnCTO()pE{W>4`_~?A};|qe{CHS2SP`=~>?Z*X}r-=mn5uA1b z@N|{Jbqar~<#t|xdY`!fbo84GfWO!E`O^!~pYBu8?x9mKPeoJkzH|!K#gr+?w_M?M zn*a7G=;yX6nCE8|enK$8^nW4fX+FVY3Epxc*5#uL|8gPt{sB|5-uq1j-X~4PJZ7e1 zo^G59`g>?9@cY_S^mFfvP=Ak$K$mAR5Bo?`x;F$!UyBPR9BntfeAd2=b zih>SnqNpzwMSC-&SXWD;z~kB|`myVI|5*w8-lq!BM^_<#?<%x6P~o{%ST`3`VIQci zLjQh5u$kZ;Rlt`M13r7kP_Azb?GDoP2{F_^Er#)58Ux*~jG?~|5ImLVFNS^a!x-BA zyT1QM9C$rAj&U5R&&6@f!%3QcK^%Cii-SI{h(mt4UGsgb8te6>YV>DFHTI^vCu24;kR)PZ{kO!6n?U48}Pp3p}mN zqW)X5$ajAhc-xQ#9Y0QR4Z+t4PVPqYox}TIH)0&GH=>>|6z)GAbbJiKvl)NWfv+p4 zV|+iJ4nFjxKL24l=<7e4(2pKXz*FBQ4W~05kW~2X`XM_G9osITi((-@P{Cm$qI|t4|xg+O*@0~#K zD5ldn7)RY4?Ell}pxm-K=+AZf{+>CYvsSI=$vNovZ?*o{=3u`5ItTsu`ei78&}GQ~ z{manLlP^R6#$5(}6xV!nFGKks>hs-~0dLzc!#E$h4E=hB;3))OxD509oy*bQ5trlr z2?R;ii=0ldjOqAt>|4)Yj&?u09Q(!ob5ZY^1b;yAT!JSNTrwB)zhf@ye}69e^Y^(J z=YI3BZV#S^_11qL^w3l1;r)tv81FUn(B5tHfY)sV2NL|Rc^K!u^MO}qzV=(6PoIzW zhRz3mC(Z|+D(9pAIrBlki|2z++&CZm>;}#E;(YL*Pv>KOoxT8k;_L-@p1%O&x?%y^ zS*_1MQF!kH;AO)C%-2H;AP@eIAgP{_0SiF~ix;B&_4<78LX>Y?h<-o55cT|WA?W_) zg}}?F3inxr`VUzIdhE9d^_{l}_^4Wh@|P~cdbw;7=J}RIkQ*Lc1o`JTi!dJ_EP|Y| z|6<^G&|=_a;$q~VyBPfWw#BIbzZYYEUR;d%`Cu{X*=GsfAG-wWuKyDBckmL7t85AS zap4l+zkUhkWziDdSC*jOTb5v+HZ1`iKeYsO*sjm-YW|OwfZq053c2vir5JbPQq(hl zDe!vTQsu)-(f-{_(VuNgF|Us=1^qm;6yterDd^#^T7I7^(BJ*9fIigg3XFH`6=?60 zE6~5DE5JY3Tmk;DQPY2=`9HV<{n~#SV9#Z+qnxn}^U>mOy}umz*=Ggj;qVpcf1ed7H+Tic8C!w=&LB9F+g*WvzC>^Y zuiF)nBhR@Kbeg&n@8?|!{M>vc@VVtm^!w+U{`!@u_iHP`7mi+u_Z2JAugpr&?ZTCy zx7$~O&UdUtKYz0lcz$~&@_5F^ku&&xQ-(Ri*-F!-LIKghKRSsCKa)3Txyc+a$$!gHU zbcG8v-&LzYw`(>1Cz{?u@KTcJ+E#-O`(2IxoO-pkb2ace{%VZ3{%Y0dG~ZPUZ@n7& z=K8C_kKfhj;%g!iQpqEA*I*s~{2KJ*xoa>FFJ1$D{p}izd!K7D&&ON~e4KPG{Ut9~j$H8k*|L`@SyHRT}-YIL)UhNu;W9AyPw|Wi6bMG4P zna%qAg2LC=V0<5}!Ft&1I@LF>Q+?w)(A6o|fnQZz2YR{eI>ptllzo^U9}^r#@cA3SSB}0Bu-A>ChrSBWyb<^xbtCXO?MBc?>_*gEr{!kfi1rt1 z{@ZQ@U2nNj{R}r^{r+6beWdyR<0g#fh?~@2a1++csGES#OKw6xmfi$BUwaeA-EtG~ z`E!MTz6t#2>o+4`&zsSoK{sRE({9H5g*T)AJ8nk(kKGJ9ZDeFkmg{aL`)dVTk5CcP-i*w-$DW^jhHm&9$Jj|6B(?cHBD1|H*a8zj+u&{p zy?HC@Kj6pE|N8tGc)04vSYHnlY~l4wa1y~=e*$^yv!7u6y>7$&o^TuJyZ>$I$Jw`G z-A>Z&u<&3CE3pLsjxY31$c#|^h*9p10?JbOFn<*nO6SKqh;O8Yfaja_{l>dc-_v)YAJ5$d`uX54;N?H>20Y|$%=^)I zgD!^Ojs3Td;1!IoyD^`K-Gg?Hx(Ck#?!kPWeh=pFOoEpZoN^EP^~^n(k5}%&xZk)3 zbhY=rSVu?Q3pw`t1WCn>)ZB~uUcMLgy>>6!>2@FJZlC)gho5pE=xzCZ*gv-32l?ca z``~{Wa6j6aem|a95gbbJm-mCu9Qsp~8=`RDPl4}UKgIlh@KeZX$36hN|C9%Sm!%It zzP$ed)c@QASU2xI06yHi1?9%JU|tuufDUhO0e{&{a5TZ^37*H}eh_p%<3Y^J{0Bkj zH$8~@c07pre)U1%eZTd<<1y<&FK4Ys`k3{=ccng0UyuGS*Yp;Besn$P`b~wOtVcih z-T-*q29zJN0rgMT=b8?>?ivCfWCiN%RRjTbnwd!nD^&5 zU>(1*0rT;WrXR5p<$7$ybMZ#Bck)K;)2DAlJ*6Af5490=dj3Z6k=a^q-bT>J75cnc z;V!NJiH)kaD13P%`uW$57{~h?fuDaW+^-ew9?^<=j%h`?KCR#%r?i5fOlw6w8GS#a z73*qIEAVn(EB3cGeg1E)?-hN1vlZj|N2|&ao6w*AHzD75H=+JxHvunwHlbXxrVrYL z^20WPuEuTxT~FSG{;b#pJYByD^{*vJVqN5JEq|Z3w_cyyHepY?*uPl`rSe_Nw8rH`v1We^z&a^(Ek2g(f@b|`d^V(-C-k(bFyM%}{w}Nk; zzdaJUfZ(Ouu`fTp9qaI*9a!&Y?SQ`BxC3(6<{j`qzfEu)!4W&L-q-BJKEHJ*=<&s! z;4j~7L%nCTq5Oh2toyBPDEE9D+WSWv)^E>U=%5r&Aun`{57a{lyPq9#Rj%o^kI(pz}XJ1irlg!{9^3 z4`W`=eHi5`9!CEv^?9DcRS%O72fv*=6mN8%HN)Vef*s#KsSdxiTcMp z33{CPBpThq3##4|F4t^Tt`#p_ycEQs~Pd*Jkw&ZE`4?m4{ zyHoQ$`ZVbKS%M@wMfQ4z_BooLdk7vx@RR={UQKYncGNSq1M6iW!5ELD1N-`rU(y^A zyzZB6eg(VVala;>%j@vhnD5{G8s!fA4c<>8IE&z2zd=36 zJxjP|d_N02!c))U{XxIQzI@eh;qQO(w~#ygKZkjo`yAHimCu3h?^pPX=hTky9OnOP z&m*4bz~`|prag~*iRZD;Eq)&Kzy5j9;j7Ps&fk6>^EvW&*!M609r(cQzXKgS@jKAt zE5AcKkr%L@zWoB8d%gg^cFGH=_ly^??uP4g#S4&Ero8|;V8#oe!<%2gdcNZY%;%#o zV7yPgfcbgu1;i_y_N?zkUh+n!R79x#s@AjQPy|0p*|n z1N=ar`~myI<*#6U{pA(R@7G=hzZ>@|;&`ULiuLxxS3x&F)#tZg1z+9wHF`(z=+|^z zzJ~SvU$0@@@4p7RJNl0pf8`&M?^1%ZnO^>gdFuWrlsk$b4Iy&QpHzW6$C^>iqF=XK!un{TMS;0-*N=<}dARDXN} z{j7Tf<(9kwJm2;P@cyX2|L_gW&jD|upU1w5^wZu1{wm&tUuFrxGiiN4@h0YP@3&MA zCpd=S^tYf#KKd5c@dX$Yejicz%XfhPSKq-nK7I%L%)WnvoN)Z#z>iM(8}K>xZ=l}=e*>P| z6h5Q*e*ZVm?J?cG-Yvg-s z$9NBXWa)b-_mlTvf4T2HjPL#TV4pwgecEdXHodQW<^#~nv=7k!9Uq{-|NQ~R_tFQT zpT8*V_95o`un*CnlRrfI@DH&+O#Kl3S*`Ga4?(xje2DSC_aXL`!#>jZ$B)pz%8$_g z%8$UOHh%;@^Xx~!>pwLAF&|?dPW%}BXxPW-??oSjuIfL=yj}4z*5CCX1Ah;EjQ#3o zA44wr)+ex|jQRw4d+ZbN+dq7waY3Jejt=+~{U7lu=)dk$=z()S1sy!{DfZLXK83yT zo1cLXF8mDrS^gRL;hmbk@iWx7{WFZ`<vi*z&cy`1@N)s3+R)d zeSvyL{S)(g;XkpTWeHwP@CkkH{V$p`uIFD!fB9dCe>*$UP4>xU1ev~`BFOzav|Bg9 z(=39#5B!86+oirB$m758Yu&^S^e{nQ=ZAm2oAhrk!6?C>5@bGoz+T-1Khp{F{N71W zU;liG$g@oA9d(2r}Ms1bKa}CCKyh96?@39}?vGJmf#R$^4#5Q1J90 zsAnZX-Ul}lWInfxAjfOGOpxa_wGUt;L8i~y1bLmWBFK1bBgpX@zahxj?6C z-S!RO>u29UyZi6kP4?eo2(rA@cVE;SC&+ws#=aQul?0g|uH6^yyh@Pe%+K`wzxGA_ z2XyZy>-lhkyk2?|)@1ws3JfHt9)c+%ecYX`_-2N@p_Xrc9E|oe3NJqx z<6dzv%CA2d^*=#yA;ISl#<(szq+5g!1k@aY`TpV%%;y1zc9Zpf$f2m`%tL{fszWiK zsY5}Ra}EWa-+UrF-+wsp{N&;2*Sm*<{{ErQ`yGMxeJDZZN9iNb&&Q6yy!?$I^XL7( z+fDSdNd(yr`0RJl-;qal6a6H0BNqG>PW2L_x1U}?*YFjeh=$sC_$DZ zW_}OlpZp&B{}Msor`}Px-%)sf{87N)*+&8I7b;wE6!P736zKQKqky0PJ__{t#!o+U?PJ>7CN=xEE)z|ZRhnNRQKpq;@E z=BJ7v^Z6zR>d~DO_-}eFD-|GW!hg&<(3g-yU`kgEDyd+a0-vB80+!sV$f?_ zG0L?UqyE>5LC^0OW1RmiMm@)tfbZ0m058i+KxZ3DK#$Lqpx$>%K<|h31s;17Wc~T< zzMz{c2(o;$t}n{HM3D7^e-UIkDC{EzRC`hVUZ^z?jx;Qu3n zEcYLHVmGmmRG)}^H=c-b-FqVXyX{2e|209DlioiOboJc<7~hBi=x5CU%-@^=y1(fA zb^5$(0Q&dz0PwMo38t97P68eO@g%(e$4Qu{o+ks(r6*&)F4X6Gg>z2^eg5cVw7>Rb z>^B=vM*lxN8SDG&r+|ODcc_4n)5B1X=(1#X#`g1I|GG7o7oq zzVr-?|EFi5{a>B|KKQL4fR6hA0Q~O!AAnA-CCGZ!%RfN}<5N>uikk z{j<^UqQT(PwSz&wYX$@V&khD2zjY4y$l2#0{hD)7{uzQCud&Y%@Y(r8FrI6NV7?z2 z0(y8x-@h~j{dr&W?Kc$je;Ps7V@42U{pI1IkmH`x=jVrF-M%&y^!Yc1pKHE-hk?!x z9ftJdhXD_#66AP|sl(8p{~m$<{B8vJ@>?S?zV0KjUVbnV>G6?R-wQ{AE^i`uF|SL4 zH*x)?psObca=gar=VDxI&P6{SJQw`u(Q|?CXZ8KQqwxONQRv?(qtLGlM*;se1X=&O zR`cyY8vMP-Xy^+QN2C8sMq~Y7HyY!;Yc$$x9SyubF&gsV2cv##$x;v$AXV-9t%1@VjR}-nF{BO16}MK2mF094(nk5 zGOV9d%P@{b`n;(O_3w2aoesT-*e@llQ+x3S3fBSJswyA{Pn6pe^07F{?QfS4^u19-<-nRDjubzl~^qPs7zn@K1 zc~aB&n}qoqI0@rRPeOX@B<#npO#HYbJx=-!vKY zuwydz?@ z2%mex^D|RG?|+>F`ufg=z|(*WK}S3V=BhmI2G$} z%~a@l`(A`~+Heu-yZIudKXeiB&}$m#X)?i8q%W|6-EEP zQ;Bg7tVH^GmFQ2b5_0pxO7O$w1lbSyvr6!*Cn_Q5byQ-$oGQ#qb(Qj!D$vVKRiKY2 zsxaU0RAC)|Glu8y#n6v|G0anC4EtCr26^iC81|!2^!b=L@RyCF-1Twr_lM)KKYS6# z{xPi@eE#NY?8m>aR=J4a27>>r#(b==!9Mg1LAHzZuEoBUsl__nRtx^!J)wGe0`hCm z1n6N|0{!?0LAJLXdkOZdrb{r6M=t^2_{Sxnt262V7uKQNGy42d9p>+>BWYbPp2^t zze=OryJ^tFz75#-9D*FLabpAWA9$(m>z9JBR9*@^r7r~^+eNUE;6WMfPX>DOlLYS} zcu^Me$iBI5k^2c&5#;l}-);oIY$2HC`DsKwnd#jkOL=`v2OckN>K0i|@WCd~|BxAw z+wPeG{&RRU=xu5<=yqYV$_>q!x3AB{epovb>-L73(3`f-#J=?TOwd{5Ea2gZSy*o` z%|d(KW`keU&c-#m!JoK+^9{BU~^I&IuMW2Vw2OKjW>vY0=)L*C13+AKU>*s^N+%_Nl{*n2>(@XPF z|EKe@uN}Am`_^#_fX~wx0MC^RFy3VgfRC#d06#Zr{+}&C{m(4`KmB-t?wboiCnqgL zzseV?9<>nr>+*%b*SdwszkVUs-L8ee_sueiLqC@;1HZX$8SwMqGSKfs%Ygr%Edw4tBp7j`shHC<>(r++@kr0!joEmn zPu8hQ*Vo5Wxp>S;r<|(VXsRZjjpv+b>2^sWzVKlP!?9p)r|sGVx0rVKG}he{LCeC$v9ULGpMkBN^&gPtUw-X(~TJeC80i% zYRtvGUr0=+a<%RcNkVtx8T+@q$i}PEshIam5}V`EjDeJp19L?%9&uJIm-3VaX9m#%M!GWpQYOgx%Pq-v;t4e4wmm(DbE z^6*45?hH*-SGy0xVu_slkWIwm#g)y)44s&jE$jYp2FGIF!_as#o|6WLr<2Jv@W2l` ziZY(D@$QV}rAfm0@^TjkfgukVc^C+d7a>8#_t^CT-*t5Ar z71A5)39B;viYT&1YtjO+qKa~EcNLc8z4y^)kDl2cCPyNtIe-Bw zfd2501dvnYFs);(x#LEcdrc%**`dOVx z*E_^dFr;Q;H1$qHG9JywolIj&-cW_fL{*f>K~owfCPe>FXJYXTI+d-8ro4_Q+O3Y+ zw8Ts(gv2D-P3YZ|SzR)biudvVu1cn}@mQZoaj`R&h8kt0)j7q*k^aJh`h)ZISJrZ} z%WVdil{$5CVot&qE}=}RXc9|9QW_d7X@r3nmFdP@WN;M^TflTe9S@lI36Bd41}<$( zWa3VF`DmHNhQ@3ya|roK`BF6{PHDBgu44MAW@N^BzUmX%Ea&9uNeC_Es0TEzkrfqX z&ag~|syM0NDFbD+gR83I4Y_D#GG2oI#3Rfy=pS*bL^9@#V6@8fSfUcOkwN3UVCUav$ zG98WS!io_(t8&R^XL=&);aak0{G-VP7?&pQwncj5pL9uWG-&Y1lpo_U{B`2>(L|D$ zCKWe%Zg9uFlxJ)UVM@rIc|5QUUK7O##rCUeYrgu1x_syiO7s?D1$w}p%d zUsQQjEiLerRk(JB90Pga4MZ@u1`0Dy~|(6@Oo>ksM&0z zBqF5iX|Ji`rqYch%|^j{g$>&|>!Yd0XtH27l7$)J#9e6xBse{4Fp`)li#DE&Ww|33 zDu_7{;)U;~tEw6^EOf^jrIsq14kr5P(PSc~?G(%_LL%e28toL$Y9s{CN^}Ef>d|V_J-dl1^s#Uw03fY8c=6636 z7FJoT;H1tbgf^M9WTKkAF%-_P(oG(h4Pm2&s*s{2J!W<@X33Wosl6-N8&ibFIv}1_ zH}xvwEnO`5$l!(qOHfX>QJ$-5BASgj8U9iTs?bZ}Vf3mYLlOezA-%vA|40;wiIi%W zK$cu{LtK8bifv}z_vn-*8*38GRQ$>1Mz$ObWn{3$W(?opnT*dMO*`eWmB`@fMCUAY zIhBoxWUiQ}%QWG>s*l%KvW7+}InqUCr;R1D{4N$bCy|OWO|fKT{dRiy%=U>G)ztmL zH0SB7=a94&!H%v#-kUA{oJN-WWI<%BXqq_}_mYWfOgux=oS>nwjFEMU3F%SRl?a*V z=ujd<@|c>1b-c|IAhO`66zdmJqVpOR7O*jqV!_%mAxpDh>O~{U5r^V!g_QOjX%2*% zT#jpv$r{U=60(@$_725@bTiuz;>l`mAu2M`kZ1!9G8%z;?nDLORHsSsEIG^=8?z?e z5V$_3n^MH#Xu1Q7vBYHHmffADfri{f`i}o)plS1#jR|TzfL>}#te%O%{pD2CUS&Pj zMzfx2#Y<)+Ra0+bR+?{!Ucx{ok+8(>Lx{`N@ea)zC{JX%Dj_Q^VE?g;v)Y(Tr=7|~ zjVh$nKicfm)zw9^qq8-GZC;|G645s#qs_pp*g3jXQ%Oll#Im@^PvM!;cUTB4Bc0cA zhzt(&LjN#S9X0~*klHwpo%_Z8Bnl9HgLx!rQm81~SSgc*%-n%$(M*^fWzk1UXHh3h zBv3{4S54f41QE$A-AKhFqKwgUP_c@hMNGq5F`Qxuso1RXCgV^rF*T%FiHse!wJCSj zvgr&DzAB!I2`&55WAXeKVC*H%`RPWdo+KY;yF|3M`f6+PG>*90J9Mw&l(?uHG0~n6pcG0^_4QF27;!409M;2R>jpC~amEQ6yc8y&Xfm5t z{1Bo@ekwxL(&?e8nQy4o!L&zUwitl0cxyy7EvSRuqDKq)qhTj zNp}kf7iP>hW+A&c*=Az8GhFjjwy~jsNChQ{Gmn9p*gR_Q%wxU(tvxWI5h4Oek>#QbEq1aun;CojziQ6)>=wfy@=5qzGB%@H;_UR66i?=hXxk_Z?6!uNE zb?0Z2{zf6$2D_~Kc_%r*m;L>1XjUOgHws%p##>J|60w0tq9uZ=d`YlGUKNT7USx5f zO-=kz2ZRz0c$dT8$i9h8bbpnuEtFJ~IHwPUg4h8bd?* zR)J)-e+&)qr@RDTKA2>!#$vh~2`QN*(f%l--(qau@_Mjy`w3f8MKTpMt8^<`og<tSvVKN$Xr-llWhL~v3c_Y4-g1YBJL^hX6H#_MhyK-~fCDzs40jc6<4Utqj(r{T{ z@%B-6f-;jE@3w3d;i2hNFII4ff08I?w5vgs4k~efi1RBe!*%8KtTR5^d%)X7<#p=Z>4ip6XOsGwr%Y*fk2PH}hbq zENV^%tF!2blnNF(3O8gMBCK4zujr#Cl;ovQr&5H7LP&}k=$goerC59I*}FcG>XTp* zDHA2?&4{!tzG`HMIwXQM#=|m_@>dhc9rO4MD^pRmy5c3{oZZf>OCu#)%gSpqS{Wx| z5$j}?*+FgbQ}}1#y`M4SC9Kk-quL3XcvYeyAsE5W{=)oMzj0vE}t#m>@IH@p>!$t zZZPVV>3n_z`MzAOuF%*?Zm~XDK^kr##cs+Ft8OIiDjO^{gBgl%g$<&_2HCv)#sN*0 z-IsnRh|Lo;CUiF0hq&h`Lq_>R*7xAIn-7O@;VE6>E4NbvHsi=}j@yuUD>gUFa+fFR zp8QI9CP>d(iC4^*ke`3i{w#*+%DA#^;$({=qYjoSZ>s{*kLn~NE! z46fBDXje9y@CYdD@mLXR=TT;PF61>2T@`045lfpYv)u7aP1@71NTk#hvDEvM>*Nol zP$GfKxYrDOmn>(72 zsyc${8d{u#iJvr!kW-Z=5o$z6-7k%qBxF)IMvh$)5W_SJ(a!XE#^#SD-JL!B4=Y4i zXEc*w3eTG5IAQ!~D?)?VN)?Cr5%bINZkcS}^G0W7NmHng&*9&_YIC`UUMzCSuWT;_ z{KBl&m`ZWiJOed`UbN>ei}WN7V-3plSE#Q(cCx9GezLEt*5J>p-|3x9)JgDijZSk3 z?K*wFLbKV#OrXzk_@`+yQO`lr5-r1a+ZhdTEw~Yp`IPe&`jCp}h<8aZ=w}l%3A0P| z)rM-*a7h%J$Osfa`RnxP*;@pOY0RPeWP8vuV7p2)jRVV1atZs#&y@F58QcgM)g;z1 z>UWn@Rmu9u$T*QZGpCWPxA31ZPaC~XQ`P)O6b|~ub}jiUT)R?cSN7~2?FKcBQw=?1 zr${`*o?(tFV;=@_fm&h0#Mqs_(h#d&@n)&YlrL+})v~>*F=Z;sSgw0-!brI;<>Au6 z5)Be`nTnK_G1s*fUP|#|^Gd5&rYx;V(dLX~C)+@)IZ|5B-V@+ApnnXCl+r*rW;W`J zB8z5C7=+qeJrRM~sp}oboUxB7r`Cr`uB^)QS*qU2-ae55Dzj;^Ly1*^%DH7AD2Tk2 z$d$PL%8NS5x)H#lzfG6Z1+2!VEG0H5XfV4q(Z{=63KPT&6|Ll+aJiaBQX5GsgDWo= z9&Jc7(iCmZ2BHodQ!L&HWl&9BXgMxsOg7*QDRqGGY?1g3Q_Z?NFjllDymOe?HPUTk zyv2YgQMUyt14w#cDr%OMn5c>~V%aWQDFGOm97>{!6UvQUjYm@r3H0O?+HR?Typ_WS zTnaCTty=dcsj4`dtx6>NNQjV81Kg~}@ml1t8x#_%{fhU8-q}8Vv(r;2=x_1UnhMy; zmshJAeQ8~@q*p=Ha%p2ahY;lwHeHkEC5X@QQwqg%>}@t4 z-_b@u9IeBtf~8lK5PD4#9(RugO7mOr#j|B4;-`jXnI8x|5TPg;<)C#DV`Vzz4fA0Q z4x$D?>Llh;@jCfq%aHuc!w}$qQR9@R6!0|n%*w;K#+*QC(&7l@FaSP3WF^xq*~!#} z6zNF#MRnP+K#?&f=(N+IG2}`%+wMzmWdwtcoN=_1iMFN+R7fDQ&WIep@TzwmjaCVc zm4f%2&2P%hU71D}*cgs8!}^TIWC>#SR5nqD*Q0P^23eMC>AfqY?!g5+KJW- zjfv-?#TC&S)^HDRDUxn@tVLxy$ z*_R!4TkshJIYDLsCl@m&+YHZB7#W+^<8SoC2!qY>oIHBr+B#U03Q0Bx5A$ab3q zuIBwDgydkO@zOZX%=cuPSJM&y6yb{XTRzK)w|cP5JQ{OgSC&vb4Ns|yl#dzcf+GDd< zY``Fe$#_n;JYp7gbZ&&fQ_xb68z6AQ+kM&(+d$8mgaq>RJa z_&hbOLXOum(K~KiwzUgfO{6@M9+}ig$r9ncDxG9Is|J9T8HQ$l5M^^jURfw_b5jx2 zlT4)Q!qVJrnw=vErPQVEXVIo8kzQI4YjVtX8UKZqx-3rgWFpuimJ_(lUhyerb!FCO zWc|jP@c3>SiCsin_4Gp)XZR|S>mZwkac?Y1~cxX=WBbXXiu4zOHbouN~|Pq!gd^% z_g$;5u;()PoXa$%QXpHb-TkO6laRB_8rT%^1vuFcS;PdZ!^gbg0}hB6&$&BfX+O~pPg%?5rE47k&J9IqkHoQFqEl1GBiOh)B!p@fkqX_rrn z(!`V>tdd8YX1*LZex0n9LRw`FW-*hNNB}#&%le)5J@~PM7e=2e^B;5ZKVnP?(&3uT zn}SF+8SIhx&c2sfF@L^?@WVr8!4TYFf;qBXDF%BSH!qYY2lYY}|O8Yy2DO;$A~qpr1KdO8;m`Sn&|_9?~h!qYcTRp(}(n z9C&hV9R5^jWM$&qDKrJ7h4Jd=IgO}!uOV7hCo#wRY&84x8rcmYK8pz7ao{_*%?V-W zxyMJFz+%V8i@~g1W;fm?um*2E+o>)+QereFf9m6EGr(vx0Ip}2!*9mNtN9PE?eH9$ zZc54s$T9)`gOqXr()N~ityFzbFV%9H{0F;365U4-QT6nrKH6aU8aV+9Ao0-gGGz)x ziW?6*qwkQorXf7lzu@sIW}s!gL1>*x_f!z?rDYy6*}@$4KHbfJK+u%Ri+ZLlqD|gXkyrWOy zZ<|zZ@!mFDKiTQPSkHGiumD}-^Gi^kkdm&qBEgb++>L%=pD*{p^Ps`m&Pj#Kgj%;!yRn`HoQlC1Ixq6ZS`vk_#8U-wg!nS^GWq926MZS=iJ87Jgi~s> z7yiVWif++tc+1OT6HjyJBh7mWo&tilR83|~`604l6@?%x`0gvWA?0g2S$gg{-jJkF zJeYSOz0d1LO(*=syba+d=2a*!@vcRnk%_Ij;DQS&Q~(Dxd8B6I6AN&qW;ugMt1}fK zT0K#hgca6$ffPtbcDf9~jKGA2sLw5sE#~DbJkU^l?q>NFKr|vr{8@cy@6@?!7xJUs ze-q5~D(k$q`#S3nPfaFB-@_>~L>sYlNaBJJ*ud($Imu2AXe2fPhQGPQxOkVA|q3}4hr`Gn9TC@ zY#(zO39!npH3{nTodC=rNXI(qT0TZS)%fMgZ+IfD55Lq~F26Y(gl5Bgs2E-DK4fI$ zD5qBBkGb><53VtyoWn1o;ubMJH*x*sGL2PWXf-8HFB7FPuy5a4T=kr@jmy99ES|18 zy^1&@MGuTmC%Jy$SC0t!Uk(S6anTPGHztCa!Q;OnHeyc$Bfdh@GBxz0y3ux5f+u~& zY7?>w5ESVIEdiOWs zvr717IZS)r`BY5^gdPa*_Bn6OUhKNHM3C=dX|vsSy|CqY-c8edauDA5yhCq2v;I3r zbe$IoBQ1`s_RKkf`=fz(m{&H_VTqyiv|h@FJb!Xwq-Ywdd5FX`}*8^2Zs> zp}B4?^sLtk%7cVXj!a}lcafC*&;UvHnT({#o>~Qbbod>G)3{QcDVDdWXSVn(lV1-f znco@rx8Jlc^6wqqMRC$U$&zQDK^D9iK_f-v^1OTaJ5sqRIaaS zg)@?H%O1*Hz%wRc;U%V2n5iq|6@(#qL0W9wguk%Jvju0`nAz2_O zCb4(5H2G}8G<2169b?|&%k#EXr%9g85N`QCnbH*Cga!i*7I`S_5s|ws_^G&wNzDtQ z5!KnO*`Ry9oL$3FVzClNU+o6)1`h<5YXr2HqnOij@rZTlsrPgDCk#1n)~Sgyhh&3{ zBs7{!LwUM-W&>%yD?-4HNMPCdj54}9M9G7xL%A2Az5>i2_ zo(kf{h!QPLRi`5r(Hj28Xq0<)EBN@LxhKFor(!%_kqY`Tdg$OXM2+!{OEi~_IXCWk z$XGWh%MF}xiuFbaQ6ZrPYj&@^8!Am|?DS}o`5H}q52FF}kd}j2Fu~!V9uN|2D&)c` zb{(rdL41pnY~+98iM=a{G4*kK%F4O&jSLn`wbQS7z=<3v$=6&o=P0BVyxi+OltJ14}e03p&qr$5ro{|_LxujdpskqVPd|P!w z&jPWBo^N%*y~ZX|lqiZ;NfOK1?YuP4Ix_uBrLC(>I7-6*O1;JTZ;aEc&mb9JJc$%U)l)v<=D(tDnC7!BzGat-~cOA!-t?`D%wQIlx7S}Bc*Pl3I;PB7M8 z^TYQNfua(}puZu1D=jEYYyo4(TqxuM%y)sp~rE}O9cI!Cp)Orq=or5 zL*98Y6Cu}#n*9Dl$0oJF+208bH5tARIzf{`yIM?Q^y!p>t?B^oyQ#Hkf7^mvVjDn z#`<`MX4E>1;~nbA7BS@{(lOC`IY`tvU?8Tlyba0-txC24w=(Go#ub7;=AXn`A`>NM z%-dmjZ<0GxBp6~MH9-1a!cw%e-oYY~w_J~s?4^O5&PyC~I~59;t=dc-->v2|8AT?t zgU2(@@kU2!%uFH^)3|HN@5oW-jl2xI?{JdDMaLqO;$kdGaBN4^&EalU!RSEO>ZvQK zgevHjVOvFp50#UCVcm8dFK~ylD`DcOUBHT}!hJGbgVSR|CmaH6A4lSLDA1PB=u4IDm6Px2 zSoDT7>xo=19&@8ekV4j}96MgEZP%(I?yI8Ui#@8_z7TK^Dv5b_V)Fl)!!}l3H;SlBrF}u%)~%9K8k&J@Fd5hd(^i%uqYnY2iJVs^5VK@`%F6zRfaEtq zd?k+2x>*IS66%^^4PCERta3-@E60~ptBElbiB@L!6ayS_Vwx_IOd(-Nu!JS#MrZR4 zs`KqzqODsm{4Zo{Xo@EEsy^@JSY@-HllY5y_cR1HP=7A>8yyhWV>&&MS$!eJQjS@u z$KVVz<)B6PwQJKl-*Vn9tp>V6YPBV!oln|D!I^DPYe2O4TY6NL2F9P*O0j|v|x3AMk=E*6N?{#EMQ&z z9g%E2_a*eRJ{^mwC&jo=d>0^A*;m1aU28w9-<*Mbg|jm#VqC)}qN21cq8@01N&XkF zfj%k2z>G#*KBM+85{P99u{7*AJ(on7AxDe?RN(s$?u}DX`#TJgxLoKIQ<#mwhbW&z z@_kfI9yIVY0>gtIfpha_eVMa%Za%ThC#6^AuBCwj`3s zzpFv`H2&(R*yw?gZ7!@Aqd(Nup1nytMb)Rycl;Fm_4_@xtVWl9FN(Y37(49P! zM$jHeKb3ZQSe71A@rb!poNz?^PU3?j?#04H@eN5nbDS3f&>RWa8!nZod~fJ-xEK>1 zf#omavsLBEvJre0#Qg}QdpO7IFcwsVkKf53abw1uw0uT@f4OBkeVdKI@zHGg+kyw# zYNJ_m)oEw%vXPvz&PC+oZD|#P2(SBoeBF`GFtE9wHzmUvL z*7~$sjz2Bnt3fRDK`Z0`zM^Y&0p00qv1Hs-+@#JVQBDR$OCR<#Q9_WzFlgcI$c6oN4$y}VRsxL`rYPy$= zt0*3#R*_=9T6v&zV!!?;756)}xZjCR|I-KdJFU3iN&Wg!#$pq};mdboasL5M|C0s| zIO&9b^j~+rS)sT>8%<{h63R1GBq}w|B(|NcOE^D3!r2XSlBKwkWKX`;=qxIks%a#V zrMMywi-o>Pt)*|Kv2UO5 zWy!`&G+8{Hgyrl&C)FU2*)s>6;o#?)y;D8=_dD~<{?7Nm@9@ul$DG-}zca|`=M0qR zv(7xxy!yeJC-F}y(eDTS`#G~`qX^~c*N4jVr!pt@={}}(%rI|)`j_=R7l)%)0Odt1l6j`{5^?d#jOv~PFXw^61Y z^uN~jot)e;my)+qvQ)!Wbj#6j-@D}H{Z=)VA=Uh9f(0cm0b$1QWShzQ>?Hk&+aF@Af^skNEA&kxISVc`*NqU+xu4##q#Hyx`A zmT7HYFYh)=>I(h6Q%h`=nU{JymT-@~UyL{FsYUYdpc-lNxOV@u|EXiSKDRQ~I~Mz& z+_L6b`zTmiEQsEWF@&e0d`PlwMk=>~ z*L=wOl+VbvU*~_p(^)X}RwZaona?B;{&8n3pP}`Rg_N+ByQ=MW@q^Fpx1k(k)_Y>S zG0D+-l6C}H?QNzi`&-cMHw%~A-m#L=FNogWz9m96F(MUBoR4v-%MTn9{g>&*7(#G( zY<}U6?!3zDBM5NaklA^|uvk+nw&4gp}Iax5*Q;`^`*h^0dXtPot?o zxBX98O}-Rb2ZF8uqw$#RPN{yqwaJ7}Ku>(r`Ah9A#mY8&(Y|HAj4k^Dqkg+oyxrW| zOI^?@=3(xV?O=uf8Ens&vW1@w$y?p-SlzzUeg!)AkE+d=p{3K;fvV*|W8Si$=`G?H z#G*Fx_GJAmw-ua@D{tzmuJ8VQ$C0vozLnOygFS}X$Ud_KMXYGx>)BUz^Z*FL1)eidPn$b>gI7N)t!W>rHh2qri}6C2w% zu&O}6iPHSvT+b^IN=W%FId+u=sjuMY+ViVhPk3J)lD<)z*&s`+fIyvJ$W=E&#;5Bw zq!gCB%Md+$1VvYurHF{vru&aFvzD$4A%(gi^#Q+|1KlPWht`L(4$CF=KRl12)#syS zy~S*KzAU_a6|Af`@)CjFOX(C5;l)JWunHRCS6F<0 zBP;WEU1u0<;H)3qW(0{~9@!a%(Azq$p#67c_%tIk?gz$p$89dh4g_JSjco;8Kmf+! zszu5$c?m6`-G3X)j8{=Ng#){4d5a31?bmwvcSIiw%}13Cw(dW}N5iBKuI#5>TLGM| z;gX`wY!HsuA{%=^*kPrMs8u!f`Sb`j@gxw3=E;xM8xJMr38L8C=ydb>dd^`9Bv4xyDLDpjmB zQip8hn}kre+UsO_VX?z$|4GLZBhnN(^1IE^zP2(7LweHbAa>J5w^s%G73ReMFKMiBuXc-2Wh@KWG(xp6F&(mXSh-BWib3|@ zpTsUA6B&|B*T~s}!R~iW#9<+~2N+r2j@b?JLDofh!%+hP4ZTG$xjm+vWHabkq?2uA#qixkCmaQt!-lW9 zjz!dl%kX*9L^ZyQ&=jW&a&ylr%?xUFQmbca28cNMH>X>+~w ze+O%Q0b76w7G3OwU+>@IV5!LDi!Le_x^PVGaT|q&kv*-jYpmkS%#2G^rVYq!U#W`H zvaeJ;gjscYNCAmE)E*5(hT>L?Mn<#wpPBzXAavi7;e>^1Mefu}-{s{zpV-xM78gBS zw|W~x*T?JIZbI+^rC zbdj5(UPw>33S+b^>RZHTxfnQFAj%i-dpmj5tYP^Cp$K39fI~vJb#0A07j z$b)X$l9)Zxuwv4Rj8F(+n+`#G+`?8xwN0}^$Ne$&tQR6(qIBaKepZWq%1hDzMh?s6 zx%PqyEn)t@$T{g;t>*!3v3~kpgOT=I)u|$^i_IeJN2eJ-r!m1_%T8IhVd0cRF^;-$ zObjv=CsL6i@_`2Tiw!vLW+)kNsoAyEC|G?9Q%P&k`0dDCA$^-8 z^S99zuvUfF95AEx%o;l`8{!`=$-cD|RI z<#YHfLmRlEJ>PV@CB%J0OL%@nUB@!jA>xY6{!Ur6;x=Hnx0$B-p{?I)O=G*~*v#|s zQD!;rwVMKg?60m`*_{TsotcyD+dhqyZA_lOXDf45cuDA0n;3^$eZ#*(_Q?f#4pa7c zcY+w6GPqnex0_HIYJ(TxQW(x{mmcq@TO6qF;`mz7VZ2d0ivnyx{8sa^;&}R2^0M%S z8F1UGBk%G$0s7f2{B4CQ7cC)WL#fXi3S7TkAB+kx-hfE+E-C4psKCT9T=k}HH2a?s zQ1UrKemzCPdPqOrY-}bSiyYzemJf_N$sP7hFuTgyx0JX%TP%X}gPuRuJ1wuDY=4W8 zB#mqo)wC5vD2;@(9DYS?Ctl^=X{OQRf~Z^VrqnS(<6b1ZTDM@CX_=DNeCb@a#x~h@ zhL}6MG`=##q?EtE`}8_SiBY#*XVG%ZBqnte4@Zz?uQ<=H9`p)XvcNi#O>G;pvHIX0 z+i65Ia8vyadcN;YWZIIDs2(E>(I7ik!DG#06MKnm)cX9y#wElUvTkS))+0i)k5ZX9 zBNN7#S~j*oHnaS0<=7c|xeczZ&NHvE=y-+GTUO%+o_j~g!Nw{q)pt)0((+KPS7 zD1qx$WwwoZTk|4E3I$XaYSXqs zO5r!#5Ho_f8{_`l=*q>g!g9RT5QIjJ(GQvnmP}NN>p{*F%x-ND#=j!OsuyboftNJn z_Dh$xx0uX9S~wJ(!n9?;S9stkzc zTG%~8QRH4cRAk*w#5Y~ZcXsmX!w#$pTiya6qKBq@2M~vNC#m%Cu^hyZn>)mIy-{Vo zxkh=)iwjdzBP7r+771EqXjy-$@;(cyke{WIwFp^ApjDV0(Jlc-|9@^N(XfYe6_EY* zq>6CK?#mI62pQt7TB&I1qDB47(O9AVr;|F2>ujFwUJ1>bCv|Nr5XquSYIth_;krO* z%5FOw=0&ktgM9*DKNvU=?9R&Keks$=QMm1$A~b9XMTNK&3fdjg4bA#}ZH)u8U4?k- z9ogev;Y%szyq!PrSrvyi5q|vQM@OEo^~>ay5g5A=PA+unofv|Hg>Hh%VmkmxQWuE`4Z%@Z2X|N0Jctoq;CB1{@}ROL=2eSu`L(tW#fo7rVcWLY zQrMIo8uV3K=IU|lS*B+7qBELNt#_k{y7M~;k%$b{E63fd1=x0gW6~VhRpi~sScDsw z?Th{NVnDf-S3XLm7rXEgSfM$U;M9&35{gj-qGQ(4VNN(~4N;J+kS!~;iiYK>&@F+e zdDs6M+zGZ6M9|JWzsv6ZKOB@Sp0c@)A&E|-N$6E^J|0*%-6{Qa%?aTMi?sj5w!=q; zdiUZ4UI`!TB~$E4uhvosPu5ei_Di|mAef-}+$Iqf zZ?GLldVJH$gXbSGYi;uEU-Nti8@ST7Y(#Ev6RmlRPowG;JawgJcPq2&Giwz}*C0$0 zFY>gXp?oC)$tmN#0e1MjZ}6DPYGfxFucrmjbO(91MVJfxkJ2?bnRsTElb9Rp19@rP z%uF-{Q|0uU-+*bvxwc?0#pVWixp@LdouC7Il7wmy&eU+}zC}BJpXh%gGA`Laf?C%UiWky0P}<00gNGLT?G*Mof~~gM(+xRdbG}pryLG!8 zq#TiN!t({q{Ha*|Kz#c;jX;reNMX*qtxV8?rRpVkwh#64gt;7c!iO`z!-U=~CS-_h zwa|&iUM2aBglSwMT?rV%h~VsNT)R}j_7jmD6pSACmuF`#pM=#DJo%BIa-!>gab&Uf zV!|Q<0>~CiZ)|at0we}&N1l(yC#&*fVV_Nx`&&r+%|lnH!y;@Z^7Yz|1tHTamF=`_ z^0ppafOfi0I(YE#<3PpTzfuihRZV@ig1{1{&<8+lsjJ4qrg}!LhhCG{l%fK%a zI2x?4u;hlLY~GhseF>R(RiYswA6Vf{))yfr@k-n=4XX+Z0@&4QZ}&VFw=2gRz6!cJ zH-`NiI^DUt`)`S~{YrS*ZD^;&gRtb$`4kr>NT}d@P6PQ~sV>(Q)cD%H&}zT_$SS$5 zKeo1S)8$e4#xqr5zBG#SJ0(mbPuS~1P;pmk?nIUQ3P}8SFU;^pzWU}vQD31`0s0F$dEWI{?=H3=vM*sm%nt2t;4GV17O)4x7YDT^UyM~{c~E57j0RDC z;1R7i9?@I4K`TBX%sqdd9?xe@lP`&}j#ZmDS2td+O~muA#JcYGV{#8w%Zzzlsmath7}-Bb1NLC)rRP85vcv= zAFV(z-Tz$`%-lO8y*5`nY=iw%+TOrZ>fKf2o*Qj5*BDt{rT2164L+}7t{G(WO(yWY zz-+C2LWjRP#GhW_58UFj3mnwoUd=5x8_NB^a$l(RF?#boBFj=%olf!xB;c2py8~h+ zI${?DuFPQz3G6yNkDF|3gR%XHi$OKVjs$ z&ywj0H0!qD5~m`QsEKEA4Yr7qT&vF{SlJ9F)l{2yaK~y9YBwK!!s{ye_Ka$>e~WBGQ8@+wp`sMA-snYe-<6Q*|AXGAOoO?LbBqHMWtn0djVW@FFaVUeWP z; z%TA3(U#nik`F?lAt$a>tc)(~M;rsdJdq4ccRlI*BU04q*VFc!+fSr@o7k=R+6V-A4 z9v_~(tD^PxasDKZxo$TO(@lvZ&PNG|Hs6JUp^IwYaiPbCfAIjZ)lYMszVUbMrTAiU6YJEgHzFDvt0RPJ{%(V!|E;g zJZ>5RpVY*cNi~aJUVl46Ls>z(i)v+zWcJz zS7?^MDTh(u^K#l`qMl?N@56THt8Icz>l<+v<@_7Ib4~y4>8Gw~iFu|i-$VXK>*>uV z_#1q3AOtkSlTTiOg!j^j_6l%Gk& zMM?nJ6?yYX)H*0|@?N96=Wdy~e8R_xR&r0c zTuoy%6HVpfalP|6*dy6FXt_5xiE_6EDFZTm|9K|YENn==EY7ltIii_&SYeA;W?Er! zq&dK+*o6f2e*3IRHKfs#Q{+oU-uH`eghcKjF!#B+*Tr}SVbcG5i{Ut$tx6>NXb84S zv8>AAFdf_jEm-eXbbf)b{34LQcV`T>w76lO)Emn#5sr(k_R(S2t7S1iy)RGKvUl=GxTfFL(2Af}sDpCgX9;tN z5%>F5h8p`^7_x{$PmH-oYsU{8Jao)3oK@jT zbbqwt=%_bI-lJ`fKU9?8{0(N}w7?z72=!iK)>6VxM z9@rOBT4f#GwhjqtQ#>zL?7qJzIB$U?TwUyCr(J6gi;%@xA~{tNI0UmzlqZ{^xQAYB z2isPt_g0XW_`tlhO)%M+!;M}GwlOMD#;XU$LD=c6%QXwWz!|db=B)ICMucmF6%fnY zvi0qdi+v=C4rqnD1KWV{d#nkQkwlan9r$)=c-Hov`NygXSyB<< zvK0-xKlS!qKCEYGM(?u@$Xuc3axWTEkIRVf!(+M&>;R{KOTG4;@8*60cZ}A#c0)M4 zBjTFT&TmgHdt--tY6ajdiw;Y*$}qi1p2Oa?^+OVuU5*KvakH?-#k zOStAnW3?WmH@w39V7}w5Rxd9mGH!nmyu`Kby9e-)q2Lw5o*7Dm1DG(EY9Z0Wm+RnGx&I9qJ}?|Tw&+BK%B-c zYR=!``eJaP!E$_f?Iaqk+bQiAw)wl@>6o1bvU}C!Ss>6q?+Y9*yR-XR$W_WazkR5v z#dw5W>B)2IwBeq4vGMpWU*^VeLkPCe{EImCR)EOZG%uh8>)T?8kXg#&gYEJuqr$#9 zl0OhdCvEsnzP7<0vAHXEWw?<*SdT3#sQ3e6yH<@oWcWDRte`%L`)}WAyA`*oU(CKT zc$3a1piDB*_8JjQ=iva8o9-^r5X>`&Z8Y1kTtY5)zwF}Ht#zeomSX>r%dAZ0td$0 zae7;ntVOOOB}zEscBeT(op-pa0PB=sc+cGH&l~(^g1pMR3BbE=Cgdv>vOcUvcz$+3 zuJp`YZ7?9X2j_J%EjhLKg2`YSQZEHzr>j)Q8c`+}1yhzPA z+7~#pcd6WH-S=T%D*k`Gb+G{$Nge#eo`^z9n0qS76mPXe9rxy$un?KBb4aYoxpz=MO*wDqIKUnt`KPtzlUjyCFHq7H5@(= zMxhs`wr3w15Q8ql^v z_d#as`F+V3-}TaX~%+tZ6>V9sQ0^6n_XV0MkBRa4lB>1?MYHfOTH^QiX6F!(cEQa z33)PC5`VWI;bDbD{1V?Kk~DFRv^i#-p1tu!FuaFcn}eA6&-{i>=F$rqKzvMtldf{qJFru})S? zCf_Aw1)?}jrF{1%&SU9qfa-ZFamw-O8#}^Fyj}P%vH9>af~c%7mgfy1@AB6+BOo#w zHsS!J?~st3Psv;CY$eGoUSq+lZ`XG1irg~aw|yNxmROlcCUVW@O~J_y>p~&S`mWI*t`8?Zm2!Z#z?-QWa0cL-Uquvcq`e&Vq6;=!8_1Gkiz%L4r)Qd@hw zo_1laG%SMNvxB$l_qL3H>^np=pqLjy-U*spf}fjVo@m#vri3niVg}vQaYgJ04n)f} zau7wbsxcXL{k_xE{AG0?@(eDlcn;y??$IZ69a&`0K5%F*X3YBtsa~SWld9IQ;D>l{ zlVCW(`T|W5rKn_)_im%RPJifimtTb3Jo%+>5MOJ_WBK><6Zo?Qp$ zYIbBYk~EA2N;wN=1wRxvzP!9^-w8v;4lioie3^+)f5Iq@JCs}X4Dvb|jTv#Ca5LUz zMGfALWT(2EixgM{A&IehJZ?^qrD(jvjeeyjeNYNpdBy&sPb2_`1!xcyC+|h z`1dxy+wV*iXzt6POO-TN?Q&VY8%h$%zf+JVuRhvfMTr|DQ=4e;xS_#Zci=inwsJAz zKd{&M?`$xiO$(%oYdrLRd4o$Iar>`WXw&1zg%R$%7r`!TK1T)Dylg$n1uV}{CzfM7 zLa?B%ri(W?Z1GnYnun_^4*O_To{OieRp}W88|N)uFKrc5<#dU)^!L0PTRIC1D#<(B zUMRA~>H57Rg?#FPy1g%4htFbO@bxaU^4jyhgxRsYDCFD3^8M2@{4~>s6R)8y7CCaC zX)6@3V&6U9VoNDlY_lHrR(ld|`8DdBbu2?P`_^##@zw_Ku0n%%_8ib>0hc5QV7 zZK+(uJ6K?9bHi^FY?O_&+M{1jD3U-sFF-t&$ROHSj);hE)Bw$b%T^~+iEM2=R^nD# zXc)433x?B!qu6&j`S0`V#Dbf5y~iHbvp!f$sPCXlhY{ODuK(!@ivw}~s0&T#r=tTvpaj7w5%_450SS_eZk0 zUaZF)*Ct5HZJEfmPLYKTz42zpEYe8Pop^#n<)D9S44P7AVZQ~iBBTHyJD50qJA-OS zY!f`Ob#A=l(~9Bfcc;HMhExj_Rx>5Jgg=lMYQt2GtdVQ#MonO7vVdiyAI4

Hjq-vJC^s)(egF-4 z_`0z1EIN@C)8SW?r1g!wyq9cvxf*uu2|dCs;#9 zpTApuwxyQmo3Tz?(h2n>Y09Qt77K0-bsoi{Icb^*!#&aYXuLM~$dX#nbnTnOx}FVY z)tNngTiR3ywJKpC_L)Mb)Wn50=Y2P!Nb6(`_eJK~fe(=((T*0i5#T;-0w5SHQ7FMQ z#gvCJjcXj_K||mt94hXFaI@8+}RHlrnIUDXAOr}8I?oS6OBu=}qTa!9MV1&ytfO)t2b#%lW0MC=t zEFo3A%X;o>=2h$r4uH^K4y)n1gc>57M6pOGW&gI*9Ze*cY-RX|(pDYdQ>`&E)>t|o z+z9e;_(H*)fq?O7YWm7%?uk6{9`6OJx*uA~y1F91tEInrfZQ!u?ZEtEhBO{zp{+tQ>7n z7xinr#A4P|A`gZ7KlA%j`HB{lZEPtSkYykiBDK zT8~@$f!U~P@&u_~ zS#VSBREcNNmlmzC2sHL1f4H*@@@biDDmn)XBcAxsNHD!MuP)g|SMM zJ=o8<_o?HyBt16V?=C^Kb6MDawcw;vdiMUHe;abA?^JukKAc4@%6!v@M00@{H2NGz zi^8`f=YTwT48k!-qBo|rezv^)TBnoFP8`W{lg9}RzdE5_zK)saM+c}v25%PiUxJi0)O|Br zNJWn05z)bOx(bI*#fG@)9}qzC6}+MR=}*dw=P%ysPbZhg94D!*%*&++W+^KluUg;I zOwfmN+_=pnu9G7Q%Cmk1yDKw%DazGJ{6CCVye}2jeo}H*RXm<_y3mC?M{)btTDI#k z5!-|^dl=+WWf2I*ub>i#qnJWi#gR-j_f)SPB(>JSRE1(bjd`m{k6fIWB`oSXO0j}Q z>agO>9rt_FjgoSMND7;##%kIo0nsx#=09`KuC8#u|E0EAzAUXZ%gv|P@K|VM1o2fe zQ?!Ma@9tOCWZw*>FP9|1z|cF1l30t;a)0Bc%99jXAf7i1vMMb##e3USL>u6jw5%nMl{EjAr$+jTn8)OEAuZ|?_7PuK0&K>PAHj}30P}>i zkAb}Devii%z%Go*>?~>6o<`$p1Zfz|?xwSs?Q}<7q!skxuy;KWM6=u6K178;xom7v zn}R|`%64GW<eDuoaz|~BFwQpw4b6HwRMBY@fZ9zzCN}zc0mp_ z%U!QoZ^gC?L4yBDO{a%_x{^G$*TnSr|dggLGR(RC+1{%i}>EMWHv;%)W4Lo33DZB^eiUFF4nNvv?mD^U)JaehZY zhJ;r-J&qZcjhaW~)`|;Ar&!QW^RX)tr=S@!zo+9$qJ>G3owg|YI!xJs@VDp}K-S1?c3(DJ;SX+vC_tv#k~#@klCamTwANzxozEZHJdpgA=t?2IBv4JZQRxFach z$$K0(wdn+=&L6c^#ZdxAC1titynYB6G@z@ScB0jA+D#>`j?`{!S3Fu^k4Lp=4Bonr zlPpsxH$2Xi6xC44snjRr7cW0vrZwu?&CS+x_}ux6U?&OxpgnZ8q0Dy3-tRP`R%t^E zo=@Zbt1x|5E6B$`e$s06uZZPsDyXFov<^uhFuOJt8aMC8%GU5G0+(KGH+??`@mxZ8Ee*&8~w>acTn5_KLmOEV4K<-RQv5cfWDvF}c>#xMM_)Q&xu4mfuqMdw_9hSoM?CtZCl2as8 z%RC{0@cmlJbjRwFHf=Q+h#F|~xOg|gK?)g26G=g1DP10%!Hn7dZco9;5b3C9hxJU- z>x38mjFw$JMU`7-&2`X`8NR|AWtant_RI;$EhxWv@vG_pA+Ds!=@QqI+s;LpZuKa2 z6v@zY4)#QwIkeD}k~)%PIn;OIxdIp6!{t+DrytRRmk=UiJ9W-4^N3sJFE-6h%WWTP zaF?A+0yE)npluHR4K6q$u+#= z*P&gwN(YS$o*-YRdZwtJte?ZxdE^nJ`L&Y4$m1_QSa6)i!9irt6Y)4kd@EH!jC{16 zFmn)Z$Q<*uss+D8O1~LI^XWmX*#;lJQptv}`e#WCN;K;;Hk2P6NJK1U7<(B;@c5-i z6-)mp4T@Q?$R-s{8(SyY(DMOOgRPEa$N1q5i2Jy+bd1>Z+QM3m?wb*@vg*^w78 zRlSNcInRRTQZ6ak>euYHVz+BB0R6V+#Os2<-zLitHQcePGGsy!GN)nbrr#VCnY{j6 z%Rd1NL`4-@4JfPD4yMkyZA__EIH|Y^vW_^8@$^Q<`~Ot!*@4C{gnytlf$BDz`7DIQ!I)Qh<{;D$JGO0btT9xCCBkJC4>!vPKYm!KN%~D8bXG`PXewDx zC?oj?hXM|^d+6>#uS4{+Ew{juM=Dd>Nnyc%AqN;eS9#NbzNZu`IKw+$yBNVLt8sQiG^b2u~Q81@|O zghh}P8q5>cS4Y4PQgUIKQd(<<0)dMSWV1a*VDG5E^e7Dk|Djmz0{-p~!DBP&5fcc( zxHMO8^iNed!xd9+>iU07~HtwSM9HEzp)ju(x?Gg!`NX zxtDydOPuY@?L0P#SEP@-C03Rqa7~L7bv`j zkQb^551~NUSO-HhX*pR>#xg0-ore(KQ#z$fD94lL zGs6)ENrt^Sx63FlI?8?C2Bf-Cnv, 2013 # mokeev1995 , 2013 # Andrey Mivrenik , 2013 -# ivlevdenis , 2013 +# invision70 , 2014 # ivlevdenis , 2013 -# Михаил Жолобов , 2013 -# mokeev1995 , 2013 -# Andrey Mivrenik , 2013 +# Mikhail Zholobov , 2013 # Ruslan Bekenev , 2013 +# SkryabinD , 2014 # softforwinxp , 2013 # zhmylove , 2013 -# Михаил Жолобов , 2013 msgid "" msgstr "" -"Project-Id-Version: RhodeCode\n" -"Report-Msgid-Bugs-To: marcin@maq.io\n" -"POT-Creation-Date: 2013-06-05 19:55+0200\n" -"PO-Revision-Date: 2013-06-07 13:54+0000\n" -"Last-Translator: Михаил Жолобов \n" -"Language-Team: Russian (http://www.transifex.com/projects/p/RhodeCode/language/ru/)\n" +"Project-Id-Version: Kallithea\n" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" +"PO-Revision-Date: 2014-02-13 14:34+0000\n" +"Last-Translator: marcinkuzminski \n" +"Language-Team: Russian " +"(http://www.transifex.com/projects/p/Kallithea/language/ru/)\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -"Language: ru\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: rhodecode/controllers/changelog.py:149 + +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 +msgid "There are no changesets yet" +msgstr "Ещё не было изменений" + +#: kallithea/controllers/changelog.py:186 msgid "All Branches" msgstr "Все ветки" -#: rhodecode/controllers/changeset.py:84 +#: kallithea/controllers/changelog.py:189 +msgid "(closed)" +msgstr "(закрыто)" + +#: kallithea/controllers/changeset.py:87 msgid "Show white space" msgstr "Отображать пробелы" -#: rhodecode/controllers/changeset.py:91 rhodecode/controllers/changeset.py:98 +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 msgid "Ignore white space" msgstr "Игнорировать пробелы" -#: rhodecode/controllers/changeset.py:164 -#, python-format -msgid "%s line context" -msgstr "контекст строки %s" - -#: rhodecode/controllers/changeset.py:345 -#: rhodecode/controllers/pullrequests.py:478 +#: kallithea/controllers/changeset.py:167 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 #, python-format msgid "Status change -> %s" msgstr "Изменение статуса -> %s" -#: rhodecode/controllers/changeset.py:376 +#: kallithea/controllers/changeset.py:386 msgid "" -"Changing status on a changeset associated with a closed pull request is not " -"allowed" -msgstr "Изменение статуса в наборе изменений ассоциированных с закрытым запросом на внесение изменений не разрешён." - -#: rhodecode/controllers/compare.py:74 -#: rhodecode/controllers/pullrequests.py:256 -msgid "There are no changesets yet" -msgstr "Ещё не было изменений" - -#: rhodecode/controllers/error.py:69 +"Changing status on a changeset associated with a closed pull request is " +"not allowed" +msgstr "" +"Нельзя редактировать статус изменений, связанных с закрытыми pull-" +"request'ами." + +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +msgid "Select changeset" +msgstr "Выбрать набор изменений" + +#: kallithea/controllers/error.py:72 msgid "Home page" msgstr "Домашняя страница" -#: rhodecode/controllers/error.py:98 -msgid "" -"The request could not be understood by the server due to malformed syntax." +#: kallithea/controllers/error.py:101 +msgid "The request could not be understood by the server due to malformed syntax." msgstr "Запрос не распознан сервером из-за неправильного синтаксиса." -#: rhodecode/controllers/error.py:101 +#: kallithea/controllers/error.py:104 msgid "Unauthorized access to resource" msgstr "Несанкционированный доступ к ресурсу" -#: rhodecode/controllers/error.py:103 +#: kallithea/controllers/error.py:106 msgid "You don't have permission to view this page" msgstr "У вас нет прав для просмотра этой страницы" -#: rhodecode/controllers/error.py:105 +#: kallithea/controllers/error.py:108 msgid "The resource could not be found" msgstr "Ресурс не найден" -#: rhodecode/controllers/error.py:107 +#: kallithea/controllers/error.py:110 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." msgstr "Сервер не может выполнить запрос, из-за неправильного условия в запросе" -#: rhodecode/controllers/feed.py:52 +#: kallithea/controllers/feed.py:55 #, python-format msgid "Changes on %s repository" msgstr "Изменения в репозитарии %s" -#: rhodecode/controllers/feed.py:53 +#: kallithea/controllers/feed.py:56 #, python-format msgid "%s %s feed" msgstr "Лента новостей %s %s" -#: rhodecode/controllers/feed.py:86 -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Changeset was too big and was cut off..." msgstr "Изменения оказались слишком большими и были вырезаны..." -#: rhodecode/controllers/feed.py:90 +#: kallithea/controllers/feed.py:93 #, python-format msgid "%s committed on %s" -msgstr "%s сделал изменения в %s" - -#: rhodecode/controllers/files.py:89 +msgstr "%s выполнил commit в %s" + +#: kallithea/controllers/files.py:92 msgid "Click here to add new file" msgstr "Нажмите чтобы добавить новый файл" -#: rhodecode/controllers/files.py:90 -#, python-format -msgid "There are no files yet %s" -msgstr "Отсутствуют файлы %s" - -#: rhodecode/controllers/files.py:271 rhodecode/controllers/files.py:339 +#: kallithea/controllers/files.py:93 +#, python-format +msgid "There are no files yet. %s" +msgstr "" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 #, python-format msgid "This repository is has been locked by %s on %s" msgstr "Репозиторий заблокировал %s в %s" -#: rhodecode/controllers/files.py:283 +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:346 +#, python-format +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "Во время фиксации изменений произошла ошибка" + +#: kallithea/controllers/files.py:373 msgid "You can only edit files with revision being a valid branch " msgstr "" - -#: rhodecode/controllers/files.py:297 -#, python-format -msgid "Edited file %s via RhodeCode" -msgstr "Файл %s отредактирован с помощью RhodeCode" - -#: rhodecode/controllers/files.py:313 +"Вы можете редактировать файлы только в редакции, связанной с существующей" +" веткой" + +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "Файл %s отредактирован с помощью Kallithea" + +#: kallithea/controllers/files.py:403 msgid "No changes" msgstr "Без изменений" -#: rhodecode/controllers/files.py:322 rhodecode/controllers/files.py:394 +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 #, python-format msgid "Successfully committed to %s" msgstr "Изменения применены в %s" -#: rhodecode/controllers/files.py:327 rhodecode/controllers/files.py:405 -msgid "Error occurred during commit" -msgstr "Во время фиксации произошла ошибка" - -#: rhodecode/controllers/files.py:351 -msgid "Added file via RhodeCode" -msgstr "Файл добавлен с помощью RhodeCode" - -#: rhodecode/controllers/files.py:368 +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "Файл добавлен с помощью Kallithea" + +#: kallithea/controllers/files.py:461 msgid "No content" msgstr "Пусто" -#: rhodecode/controllers/files.py:372 +#: kallithea/controllers/files.py:465 msgid "No filename" msgstr "Безымянный" -#: rhodecode/controllers/files.py:397 +#: kallithea/controllers/files.py:490 msgid "Location must be relative path and must not contain .. in path" -msgstr "Расположение должно быть относительным путем, и не должно содержать \"..\" в пути" - -#: rhodecode/controllers/files.py:431 +msgstr "" +"Расположение должно быть относительным путем, и не должно содержать " +"\"..\" в пути" + +#: kallithea/controllers/files.py:524 msgid "Downloads disabled" msgstr "Возможность скачивать отключена" -#: rhodecode/controllers/files.py:442 +#: kallithea/controllers/files.py:535 #, python-format msgid "Unknown revision %s" msgstr "Неизвестная версия %s" -#: rhodecode/controllers/files.py:444 +#: kallithea/controllers/files.py:537 msgid "Empty repository" msgstr "Пустой репозитарий" -#: rhodecode/controllers/files.py:446 +#: kallithea/controllers/files.py:539 msgid "Unknown archive type" msgstr "Неизвестный тип архива" -#: rhodecode/controllers/files.py:631 -#: rhodecode/templates/changeset/changeset_range.html:9 -#: rhodecode/templates/email_templates/pull_request.html:12 -#: rhodecode/templates/pullrequests/pullrequest.html:124 +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 msgid "Changesets" msgstr "Набор изменений" -#: rhodecode/controllers/files.py:632 -#: rhodecode/controllers/pullrequests.py:149 -#: rhodecode/controllers/summary.py:76 rhodecode/model/scm.py:682 -#: rhodecode/templates/switch_to_list.html:3 -#: rhodecode/templates/branches/branches.html:10 +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 msgid "Branches" msgstr "Ветки" -#: rhodecode/controllers/files.py:633 -#: rhodecode/controllers/pullrequests.py:150 -#: rhodecode/controllers/summary.py:77 rhodecode/model/scm.py:693 -#: rhodecode/templates/switch_to_list.html:15 -#: rhodecode/templates/tags/tags.html:10 +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 msgid "Tags" msgstr "Метки" -#: rhodecode/controllers/forks.py:176 -#, python-format -msgid "Forked repository %s as %s" -msgstr "Сделан форк(копия) репозитория %s на %s" - -#: rhodecode/controllers/forks.py:190 +#: kallithea/controllers/forks.py:191 #, python-format msgid "An error occurred during repository forking %s" msgstr "Произошла ошибка во время создания форка репозитория %s" -#: rhodecode/controllers/journal.py:110 rhodecode/controllers/journal.py:153 +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "Репозитории" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "Ветка" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "Тэги" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "Закладки" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 msgid "public journal" msgstr "общедоступный журнал" -#: rhodecode/controllers/journal.py:114 rhodecode/controllers/journal.py:157 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 msgid "journal" msgstr "журнал" -#: rhodecode/controllers/login.py:138 -msgid "You have successfully registered into RhodeCode" -msgstr "Регистрация в RhodeCode прошла успешно" - -#: rhodecode/controllers/login.py:159 +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" +msgstr "Регистрация в Kallithea прошла успешно" + +#: kallithea/controllers/login.py:237 msgid "Your password reset link was sent" msgstr "Ссылка для сброса пароля отправлена" -#: rhodecode/controllers/login.py:179 +#: kallithea/controllers/login.py:257 msgid "" -"Your password reset was successful, new password has been sent to your email" +"Your password reset was successful, new password has been sent to your " +"email" msgstr "Сброс пароля прошел успешно, новый пароль был отправлен на ваш email" -#: rhodecode/controllers/pullrequests.py:136 -#: rhodecode/templates/changeset/changeset.html:10 -#: rhodecode/templates/email_templates/changeset_comment.html:8 +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 msgid "Changeset" msgstr "Изменения" -#: rhodecode/controllers/pullrequests.py:146 +#: kallithea/controllers/pullrequests.py:157 msgid "Special" msgstr "Специальный" -#: rhodecode/controllers/pullrequests.py:147 +#: kallithea/controllers/pullrequests.py:158 msgid "Peer branches" -msgstr "" - -#: rhodecode/controllers/pullrequests.py:148 rhodecode/model/scm.py:688 -#: rhodecode/templates/switch_to_list.html:28 -#: rhodecode/templates/bookmarks/bookmarks.html:10 +msgstr "Ветки участника" + +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 msgid "Bookmarks" msgstr "Закладки" -#: rhodecode/controllers/pullrequests.py:321 +#: kallithea/controllers/pullrequests.py:330 msgid "Pull request requires a title with min. 3 chars" msgstr "Заголовок Pull запроса должен быть не менее 3-х символов" -#: rhodecode/controllers/pullrequests.py:323 -msgid "Error creating pull request" -msgstr "Произошла ошибка при создании Pull запроса" - -#: rhodecode/controllers/pullrequests.py:343 +#: kallithea/controllers/pullrequests.py:332 +#, python-format +msgid "Error creating pull request: %s" +msgstr "Ошибка при создании pull запроса: %s" + +#: kallithea/controllers/pullrequests.py:354 msgid "Successfully opened new pull request" msgstr "Pull запрос создан успешно" -#: rhodecode/controllers/pullrequests.py:346 +#: kallithea/controllers/pullrequests.py:357 msgid "Error occurred during sending pull request" msgstr "Произошла ошибка при создании Pull запроса" -#: rhodecode/controllers/pullrequests.py:385 +#: kallithea/controllers/pullrequests.py:397 msgid "Successfully deleted pull request" msgstr "Pull запрос успешно удалён" -#: rhodecode/controllers/pullrequests.py:481 +#: kallithea/controllers/pullrequests.py:485 msgid "Closing with" msgstr "Закрытый с" -#: rhodecode/controllers/pullrequests.py:518 -msgid "" -"Closing pull request on other statuses than rejected or approved forbidden" -msgstr "" - -#: rhodecode/controllers/search.py:132 +#: kallithea/controllers/pullrequests.py:522 +msgid "Closing pull request on other statuses than rejected or approved forbidden" +msgstr "" +"Закрытие pull-requst'а со статусом, отличным от 'Одобрено' или " +"'Отклонено' " + +#: kallithea/controllers/search.py:135 msgid "Invalid search query. Try quoting it." msgstr "Недопустимый поисковый запрос. Попробуйте заключить его в кавычки." -#: rhodecode/controllers/search.py:137 +#: kallithea/controllers/search.py:140 msgid "There is no index to search in. Please run whoosh indexer" -msgstr "Индексы отсутствуют. Пожалуйста, запустите индексатор." - -#: rhodecode/controllers/search.py:141 +msgstr "Индексы отсутствуют. Пожалуйста, запустите индексатор Whoosh." + +#: kallithea/controllers/search.py:144 msgid "An error occurred during this search operation" msgstr "Произошла ошибка при выполнении этого поиска" -#: rhodecode/controllers/summary.py:182 +#: kallithea/controllers/summary.py:203 msgid "No data loaded yet" msgstr "Данные пока не загружены" -#: rhodecode/controllers/summary.py:188 -#: rhodecode/templates/summary/summary.html:149 +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 msgid "Statistics are disabled for this repository" msgstr "Статистические данные отключены для этого репозитария" -#: rhodecode/controllers/admin/defaults.py:96 +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "Настройки авторизации успешно обновлены" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "произошла ошибка при обновлении настроек авторизации" + +#: kallithea/controllers/admin/defaults.py:97 msgid "Default settings updated successfully" msgstr "Стандартные настройки успешно обновлены" -#: rhodecode/controllers/admin/defaults.py:110 +#: kallithea/controllers/admin/defaults.py:111 msgid "Error occurred during update of defaults" msgstr "Произошла ошибка при обновлении стандартных настроек" -#: rhodecode/controllers/admin/gists.py:56 +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 msgid "forever" msgstr "навсегда" -#: rhodecode/controllers/admin/gists.py:57 +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 msgid "5 minutes" msgstr "5 минут" -#: rhodecode/controllers/admin/gists.py:58 +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 msgid "1 hour" msgstr "1 час" -#: rhodecode/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 msgid "1 day" msgstr "1 день" -#: rhodecode/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 msgid "1 month" msgstr "1 месяц" -#: rhodecode/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 msgid "Lifetime" msgstr "Срок" -#: rhodecode/controllers/admin/gists.py:127 +#: kallithea/controllers/admin/gists.py:147 msgid "Error occurred during gist creation" msgstr "Произошла ошибка во время создания сути" -#: rhodecode/controllers/admin/gists.py:165 +#: kallithea/controllers/admin/gists.py:185 #, python-format msgid "Deleted gist %s" msgstr "Запись gist %s удалена" -#: rhodecode/controllers/admin/ldap_settings.py:50 -msgid "BASE" -msgstr "BASE" - -#: rhodecode/controllers/admin/ldap_settings.py:51 -msgid "ONELEVEL" -msgstr "ONELEVEL" - -#: rhodecode/controllers/admin/ldap_settings.py:52 -msgid "SUBTREE" -msgstr "SUBTREE" - -#: rhodecode/controllers/admin/ldap_settings.py:56 -msgid "NEVER" -msgstr "NEVER" - -#: rhodecode/controllers/admin/ldap_settings.py:57 -msgid "ALLOW" -msgstr "ALLOW" - -#: rhodecode/controllers/admin/ldap_settings.py:58 -msgid "TRY" -msgstr "TRY" - -#: rhodecode/controllers/admin/ldap_settings.py:59 -msgid "DEMAND" -msgstr "DEMAND" - -#: rhodecode/controllers/admin/ldap_settings.py:60 -msgid "HARD" -msgstr "HARD" - -#: rhodecode/controllers/admin/ldap_settings.py:64 -msgid "No encryption" -msgstr "Без шифрования" - -#: rhodecode/controllers/admin/ldap_settings.py:65 -msgid "LDAPS connection" -msgstr "Соединение LDAPS" - -#: rhodecode/controllers/admin/ldap_settings.py:66 -msgid "START_TLS on LDAP connection" -msgstr "Использовать START_TLS при соединении по LDAP" - -#: rhodecode/controllers/admin/ldap_settings.py:124 -msgid "LDAP settings updated successfully" -msgstr "Настройки LDAP успешно обновлены" - -#: rhodecode/controllers/admin/ldap_settings.py:128 -msgid "Unable to activate ldap. The \"python-ldap\" library is missing." -msgstr "Невозможно использовать LDAP. Библиотека \"python-ldap\" недоступна." - -#: rhodecode/controllers/admin/ldap_settings.py:145 -msgid "Error occurred during update of ldap settings" -msgstr "Произошла ошибка при обновлении настроек LDAP" - -#: rhodecode/controllers/admin/permissions.py:58 -#: rhodecode/controllers/admin/permissions.py:62 -#: rhodecode/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "" +"Вы не можете изменить данные пользователя, поскольку это критично для " +"работы всего приложения" + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "Ваша учетная запись успешно обновлена" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "Произошла ошибка при обновлении пользователя %s" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "Пользователю добавлен E-mail %s" + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "Произошла ошибка при сохранении E-mail" + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "E-mail пользователя удалён" + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 msgid "None" msgstr "Ничего" -#: rhodecode/controllers/admin/permissions.py:59 -#: rhodecode/controllers/admin/permissions.py:63 -#: rhodecode/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 msgid "Read" msgstr "Чтение" -#: rhodecode/controllers/admin/permissions.py:60 -#: rhodecode/controllers/admin/permissions.py:64 -#: rhodecode/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 msgid "Write" msgstr "Запись" -#: rhodecode/controllers/admin/permissions.py:61 -#: rhodecode/controllers/admin/permissions.py:65 -#: rhodecode/controllers/admin/permissions.py:69 -#: rhodecode/templates/admin/defaults/defaults.html:9 -#: rhodecode/templates/admin/ldap/ldap.html:9 -#: rhodecode/templates/admin/permissions/permissions.html:9 -#: rhodecode/templates/admin/repos/repo_add.html:10 -#: rhodecode/templates/admin/repos/repo_add.html:14 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:13 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:9 -#: rhodecode/templates/admin/users/user_add.html:8 -#: rhodecode/templates/admin/users/user_edit.html:9 -#: rhodecode/templates/admin/users/user_edit.html:133 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/admin/users/users.html:85 -#: rhodecode/templates/admin/users_groups/users_group_add.html:8 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 -#: rhodecode/templates/admin/users_groups/users_groups.html:9 -#: rhodecode/templates/base/base.html:317 -#: rhodecode/templates/base/base.html:318 -#: rhodecode/templates/base/base.html:324 -#: rhodecode/templates/base/base.html:325 +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 msgid "Admin" msgstr "Администратор" -#: rhodecode/controllers/admin/permissions.py:72 -#: rhodecode/controllers/admin/permissions.py:83 -#: rhodecode/controllers/admin/permissions.py:86 -#: rhodecode/controllers/admin/permissions.py:89 -#: rhodecode/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 msgid "Disabled" msgstr "Отключено" -#: rhodecode/controllers/admin/permissions.py:74 +#: kallithea/controllers/admin/permissions.py:78 msgid "Allowed with manual account activation" -msgstr "Разрешено, с ручной активацией учётной записи" - -#: rhodecode/controllers/admin/permissions.py:76 +msgstr "Разрешена, с ручной активацией учётной записи" + +#: kallithea/controllers/admin/permissions.py:80 msgid "Allowed with automatic account activation" -msgstr "Разрешено, с автоматической активацией учётной записи" - -#: rhodecode/controllers/admin/permissions.py:79 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1439 rhodecode/model/db.py:1444 +msgstr "Разрешена, с автоматической активацией учётной записи" + +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 msgid "Manual activation of external account" msgstr "Ручная активация внешней учетной записи" -#: rhodecode/controllers/admin/permissions.py:80 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1440 rhodecode/model/db.py:1445 +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 msgid "Automatic activation of external account" msgstr "Автоматическая активация внешней учетной записи" -#: rhodecode/controllers/admin/permissions.py:84 -#: rhodecode/controllers/admin/permissions.py:87 -#: rhodecode/controllers/admin/permissions.py:90 -#: rhodecode/controllers/admin/permissions.py:93 +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 msgid "Enabled" msgstr "Включено" -#: rhodecode/controllers/admin/permissions.py:138 -msgid "Default permissions updated successfully" -msgstr "Стандартные привилегии успешно обновлены" - -#: rhodecode/controllers/admin/permissions.py:152 +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "Глобальные привилегии успешно обновлены" + +#: kallithea/controllers/admin/permissions.py:139 msgid "Error occurred during update of permissions" -msgstr "Произошла ошибка во время обновления привелегий" - -#: rhodecode/controllers/admin/repos.py:128 -msgid "--REMOVE FORK--" -msgstr "--УДАЛИТЬ ФОРК--" - -#: rhodecode/controllers/admin/repos.py:168 +msgstr "Произошла ошибка во время обновления привилегий" + +#: kallithea/controllers/admin/repo_groups.py:186 +#, python-format +msgid "Created repository group %s" +msgstr "Создана новая группа репозиториев %s" + +#: kallithea/controllers/admin/repo_groups.py:198 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "Произошла ошибка при создании группы репозиториев %s" + +#: kallithea/controllers/admin/repo_groups.py:256 +#, python-format +msgid "Updated repository group %s" +msgstr "Группа репозиториев %s обновлена" + +#: kallithea/controllers/admin/repo_groups.py:271 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "Произошла ошибка при обновлении группы репозиториев %s" + +#: kallithea/controllers/admin/repo_groups.py:289 +#, python-format +msgid "This group contains %s repositores and cannot be deleted" +msgstr "Данная группа содержит %s репозитариев и не может быть удалена" + +#: kallithea/controllers/admin/repo_groups.py:296 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "Группа содержит в себе %s подгрупп и не может быть удалён" + +#: kallithea/controllers/admin/repo_groups.py:302 +#, python-format +msgid "Removed repository group %s" +msgstr "Группа репозиториев %s удалена" + +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "Произошла ошибка при удалении группы репозиториев %s" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "Администратор не может отозвать свои привелегии" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "Привилегии группы репозиториев обновлены" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "Произошла ошибка при отзыве привелегии" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "Произошла ошибка при создании репозитория %s" + +#: kallithea/controllers/admin/repos.py:237 #, python-format msgid "Created repository %s from %s" msgstr "Репозиторий %s создан из %s" -#: rhodecode/controllers/admin/repos.py:174 +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "Сделан форк(копия) репозитория %s на %s" + +#: kallithea/controllers/admin/repos.py:249 #, python-format msgid "Created repository %s" msgstr "Репозиторий %s создан" -#: rhodecode/controllers/admin/repos.py:197 -#, python-format -msgid "Error creating repository %s" -msgstr "Произошла ошибка при создании репозитория %s" - -#: rhodecode/controllers/admin/repos.py:270 +#: kallithea/controllers/admin/repos.py:289 #, python-format msgid "Repository %s updated successfully" msgstr "Репозитарий %s успешно обновлён" -#: rhodecode/controllers/admin/repos.py:288 +#: kallithea/controllers/admin/repos.py:307 #, python-format msgid "Error occurred during update of repository %s" msgstr "Произошла ошибка во время обновления репозитория %s" -#: rhodecode/controllers/admin/repos.py:315 +#: kallithea/controllers/admin/repos.py:334 #, python-format msgid "Detached %s forks" msgstr "Форки %s отсоединены" -#: rhodecode/controllers/admin/repos.py:318 +#: kallithea/controllers/admin/repos.py:337 #, python-format msgid "Deleted %s forks" msgstr "Удалены форки репозитория %s" -#: rhodecode/controllers/admin/repos.py:323 +#: kallithea/controllers/admin/repos.py:342 #, python-format msgid "Deleted repository %s" msgstr "Репозиторий %s удалён" -#: rhodecode/controllers/admin/repos.py:326 +#: kallithea/controllers/admin/repos.py:345 #, python-format msgid "Cannot delete %s it still contains attached forks" msgstr "Невозможно удалить %s, он всё-ещё содержит форки" -#: rhodecode/controllers/admin/repos.py:331 +#: kallithea/controllers/admin/repos.py:350 #, python-format msgid "An error occurred during deletion of %s" msgstr "Произошла ошибка во время удаления %s" -#: rhodecode/controllers/admin/repos.py:345 +#: kallithea/controllers/admin/repos.py:402 msgid "Repository permissions updated" msgstr "Привилегии репозитория обновлены" -#: rhodecode/controllers/admin/repos.py:375 -#: rhodecode/controllers/admin/repos_groups.py:332 -#: rhodecode/controllers/admin/users_groups.py:312 -msgid "An error occurred during revoking of permission" -msgstr "Произошла ошибка при отзыве привелегии" - -#: rhodecode/controllers/admin/repos.py:392 -msgid "An error occurred during deletion of repository stats" -msgstr "Произошла ошибка при удалении статистики репозитория" - -#: rhodecode/controllers/admin/repos.py:409 -msgid "An error occurred during cache invalidation" -msgstr "Произошла ошибка при очистке кэша" - -#: rhodecode/controllers/admin/repos.py:429 -#: rhodecode/controllers/admin/repos.py:456 +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "Произошла ошибка при создании поля" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "Произошла ошибка при удалении поля" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "" + +#: kallithea/controllers/admin/repos.py:522 +msgid "Updated repository visibility in public journal" +msgstr "Видимость репозитория в публичном журнале обновлена" + +#: kallithea/controllers/admin/repos.py:526 +msgid "An error occurred during setting this repository in public journal" +msgstr "Произошла ошибка при установке репозитария в общедоступный журнал" + +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 +msgid "Token mismatch" +msgstr "Несовпадение токенов" + +#: kallithea/controllers/admin/repos.py:546 +msgid "Nothing" +msgstr "Ничего" + +#: kallithea/controllers/admin/repos.py:548 +#, python-format +msgid "Marked repo %s as fork of %s" +msgstr "Репозиторий %s отмечен как форк %s" + +#: kallithea/controllers/admin/repos.py:555 +msgid "An error occurred during this operation" +msgstr "Произошла ошибка при выполнении операции" + +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "Закрытый репозиторий" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "Открытый репозиторий" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 msgid "An error occurred during unlocking" msgstr "Произошла ошибка во время разблокирования" -#: rhodecode/controllers/admin/repos.py:447 +#: kallithea/controllers/admin/repos.py:595 msgid "Unlocked" msgstr "Разблокировано" -#: rhodecode/controllers/admin/repos.py:450 +#: kallithea/controllers/admin/repos.py:598 msgid "Locked" msgstr "Заблокировано" -#: rhodecode/controllers/admin/repos.py:452 +#: kallithea/controllers/admin/repos.py:600 #, python-format msgid "Repository has been %s" msgstr "Репозиторий %s" -#: rhodecode/controllers/admin/repos.py:476 -msgid "Updated repository visibility in public journal" -msgstr "Видимость репозитория в публичном журнале обновлена" - -#: rhodecode/controllers/admin/repos.py:480 -msgid "An error occurred during setting this repository in public journal" -msgstr "Произошла ошибка при установке репозитария в общедоступный журнал" - -#: rhodecode/controllers/admin/repos.py:485 rhodecode/model/validators.py:302 -msgid "Token mismatch" -msgstr "Несовпадение токенов" - -#: rhodecode/controllers/admin/repos.py:498 +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "Произошла ошибка при очистке кэша" + +#: kallithea/controllers/admin/repos.py:637 msgid "Pulled from remote location" -msgstr "Обновлено из удалённого репозитория" - -#: rhodecode/controllers/admin/repos.py:501 +msgstr "Внесены изменения из удалённого репозитория" + +#: kallithea/controllers/admin/repos.py:640 msgid "An error occurred during pull from remote location" -msgstr "Произошла ошибка при получении данных из удалённого репозитория " - -#: rhodecode/controllers/admin/repos.py:517 -msgid "Nothing" -msgstr "Ничего" - -#: rhodecode/controllers/admin/repos.py:519 -#, python-format -msgid "Marked repo %s as fork of %s" -msgstr "Отмеченный репозиторий %s форком %s" - -#: rhodecode/controllers/admin/repos.py:523 -msgid "An error occurred during this operation" -msgstr "Произошла ошибка при выполнении операции" - -#: rhodecode/controllers/admin/repos.py:562 -msgid "An error occurred during creation of field" -msgstr "Произошла ошибка при создании поля" - -#: rhodecode/controllers/admin/repos.py:576 -msgid "An error occurred during removal of field" -msgstr "Произошла ошибка при удалении поля" - -#: rhodecode/controllers/admin/repos_groups.py:147 -#, python-format -msgid "Created repository group %s" -msgstr "Создана новая группа репозиториев %s" - -#: rhodecode/controllers/admin/repos_groups.py:159 -#, python-format -msgid "Error occurred during creation of repository group %s" -msgstr "Произошла ошибка при создании группы репозиториев %s" - -#: rhodecode/controllers/admin/repos_groups.py:217 -#, python-format -msgid "Updated repository group %s" -msgstr "Группа репозиториев %s обновлена" - -#: rhodecode/controllers/admin/repos_groups.py:232 -#, python-format -msgid "Error occurred during update of repository group %s" -msgstr "Произошла ошибка при обновлении группы репозиториев %s" - -#: rhodecode/controllers/admin/repos_groups.py:250 -#, python-format -msgid "This group contains %s repositores and cannot be deleted" -msgstr "Данная группа содержит %s репозитариев и не может быть удалена" - -#: rhodecode/controllers/admin/repos_groups.py:257 -#, python-format -msgid "This group contains %s subgroups and cannot be deleted" -msgstr "Группа содержит в себе %s подгрупп и не может быть удалён" - -#: rhodecode/controllers/admin/repos_groups.py:263 -#, python-format -msgid "Removed repository group %s" -msgstr "Группа репозиториев %s удалена" - -#: rhodecode/controllers/admin/repos_groups.py:268 -#, python-format -msgid "Error occurred during deletion of repository group %s" -msgstr "Произошла ошибка при удалении группы репозиториев %s" - -#: rhodecode/controllers/admin/repos_groups.py:279 -#: rhodecode/controllers/admin/repos_groups.py:314 -#: rhodecode/controllers/admin/users_groups.py:300 -msgid "Cannot revoke permission for yourself as admin" -msgstr "Администратор не может отозвать свои привелегии" - -#: rhodecode/controllers/admin/repos_groups.py:294 -msgid "Repository Group permissions updated" -msgstr "Привилегии группы репозиториев обновлены" - -#: rhodecode/controllers/admin/settings.py:123 +msgstr "Произошла ошибка при внесении изменений из удалённого репозитория" + +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "Произошла ошибка при удалении статистики репозитория" + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "Обновлены настройки VCS" + +#: kallithea/controllers/admin/settings.py:176 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "Произошла ошибка при обновлении настроек приложения" + +#: kallithea/controllers/admin/settings.py:215 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" msgstr "Репозитории успешно пересканированы, добавлено: %s ; удалено: %s" -#: rhodecode/controllers/admin/settings.py:132 -msgid "Whoosh reindex task scheduled" -msgstr "Запланирована переиндексация базы Whoosh" - -#: rhodecode/controllers/admin/settings.py:163 +#: kallithea/controllers/admin/settings.py:270 msgid "Updated application settings" msgstr "Обновленные параметры настройки приложения" -#: rhodecode/controllers/admin/settings.py:167 -#: rhodecode/controllers/admin/settings.py:304 -msgid "Error occurred during updating application settings" -msgstr "Произошла ошибка при обновлении настроек приложения" - -#: rhodecode/controllers/admin/settings.py:219 +#: kallithea/controllers/admin/settings.py:327 msgid "Updated visualisation settings" msgstr "Настройки визуализации обновлены" -#: rhodecode/controllers/admin/settings.py:224 +#: kallithea/controllers/admin/settings.py:332 msgid "Error occurred during updating visualisation settings" msgstr "Произошла ошибка при обновлении настроек визуализации" -#: rhodecode/controllers/admin/settings.py:300 -msgid "Updated VCS settings" -msgstr "Обновлены настройки VCS" - -#: rhodecode/controllers/admin/settings.py:314 +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "Пожалуйста, введите адрес электронной почты" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "Задача отправки Email создана" + +#: kallithea/controllers/admin/settings.py:400 msgid "Added new hook" -msgstr "Добавлен новый хук" - -#: rhodecode/controllers/admin/settings.py:326 +msgstr "Добавлена новая ловушка" + +#: kallithea/controllers/admin/settings.py:414 msgid "Updated hooks" -msgstr "Обновлённые хуки" - -#: rhodecode/controllers/admin/settings.py:330 +msgstr "Обновлённые ловушки" + +#: kallithea/controllers/admin/settings.py:418 msgid "Error occurred during hook creation" msgstr "произошла ошибка при создании хука" -#: rhodecode/controllers/admin/settings.py:349 -msgid "Email task created" -msgstr "Письмо поставлено в очередь" - -#: rhodecode/controllers/admin/settings.py:413 -msgid "You can't edit this user since it's crucial for entire application" -msgstr "Вы не можете изменить данные пользователя, поскольку это критично для работы всего приложения" - -#: rhodecode/controllers/admin/settings.py:455 -msgid "Your account was updated successfully" -msgstr "Ваша учетная запись успешно обновлена" - -#: rhodecode/controllers/admin/settings.py:470 -#: rhodecode/controllers/admin/users.py:198 -#, python-format -msgid "Error occurred during update of user %s" -msgstr "Произошла ошибка при обновлении пользователя %s" - -#: rhodecode/controllers/admin/users.py:130 +#: kallithea/controllers/admin/settings.py:444 +msgid "Whoosh reindex task scheduled" +msgstr "Запланирована переиндексация базы Whoosh" + +#: kallithea/controllers/admin/user_groups.py:150 +#, python-format +msgid "Created user group %s" +msgstr "Создана группа пользователей %s" + +#: kallithea/controllers/admin/user_groups.py:161 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "Произошла ошибка при создании группы пользователей %s" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Updated user group %s" +msgstr "Группа пользователей %s обновлена" + +#: kallithea/controllers/admin/user_groups.py:221 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "Произошла ошибка при обновлении группы пользователей %s" + +#: kallithea/controllers/admin/user_groups.py:239 +msgid "Successfully deleted user group" +msgstr "Группа пользователей успешно удалена" + +#: kallithea/controllers/admin/user_groups.py:244 +msgid "An error occurred during deletion of user group" +msgstr "Произошла ошибка при удалении группы пользователей" + +#: kallithea/controllers/admin/user_groups.py:311 +msgid "Target group cannot be the same" +msgstr "Целевая группа не может быть такой же" + +#: kallithea/controllers/admin/user_groups.py:317 +msgid "User Group permissions updated" +msgstr "Привилегии группы пользователей обновлены" + +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "Обновлены привилегии" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "Произошла ошибка при сохранении привилегий" + +#: kallithea/controllers/admin/users.py:135 #, python-format msgid "Created user %s" msgstr "Пользователь %s создан" -#: rhodecode/controllers/admin/users.py:142 +#: kallithea/controllers/admin/users.py:149 #, python-format msgid "Error occurred during creation of user %s" msgstr "Произошла ошибка при создании пользователя %s" -#: rhodecode/controllers/admin/users.py:176 +#: kallithea/controllers/admin/users.py:188 msgid "User updated successfully" msgstr "Пользователь успешно обновлён" -#: rhodecode/controllers/admin/users.py:214 +#: kallithea/controllers/admin/users.py:223 msgid "Successfully deleted user" msgstr "Пользователь успешно удалён" -#: rhodecode/controllers/admin/users.py:219 +#: kallithea/controllers/admin/users.py:228 msgid "An error occurred during deletion of user" msgstr "Произошла ошибка при удалении пользователя" -#: rhodecode/controllers/admin/users.py:234 +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 msgid "You can't edit this user" msgstr "Вы не можете редактировать данного пользователя" -#: rhodecode/controllers/admin/users.py:293 -#: rhodecode/controllers/admin/users_groups.py:372 -msgid "Updated permissions" -msgstr "Обновлены привилегии" - -#: rhodecode/controllers/admin/users.py:297 -#: rhodecode/controllers/admin/users_groups.py:376 -msgid "An error occurred during permissions saving" -msgstr "Произошла ошибка при сохранении привилегий" - -#: rhodecode/controllers/admin/users.py:311 -#, python-format -msgid "Added email %s to user" -msgstr "Пользователю добавлен E-mail %s" - -#: rhodecode/controllers/admin/users.py:317 -msgid "An error occurred during email saving" -msgstr "Произошла ошибка при сохранении E-mail" - -#: rhodecode/controllers/admin/users.py:327 -msgid "Removed email from user" -msgstr "E-mail пользователя удалён" - -#: rhodecode/controllers/admin/users.py:340 -#, python-format -msgid "Added ip %s to user" -msgstr "Пользователю добавлен ip %s" - -#: rhodecode/controllers/admin/users.py:346 +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "Добавлен IP %s в белый список пользователя" + +#: kallithea/controllers/admin/users.py:489 msgid "An error occurred during ip saving" msgstr "Произошла ошибка при сохранении IP" -#: rhodecode/controllers/admin/users.py:358 -msgid "Removed ip from user" -msgstr "Ip пользователя удалён" - -#: rhodecode/controllers/admin/users_groups.py:162 -#, python-format -msgid "Created user group %s" -msgstr "Создана группа пользователей %s" - -#: rhodecode/controllers/admin/users_groups.py:173 -#, python-format -msgid "Error occurred during creation of user group %s" -msgstr "Произошла ошибка при создании группы пользователей %s" - -#: rhodecode/controllers/admin/users_groups.py:210 -#, python-format -msgid "Updated user group %s" -msgstr "Группа пользователей %s обновлена" - -#: rhodecode/controllers/admin/users_groups.py:232 -#, python-format -msgid "Error occurred during update of user group %s" -msgstr "Произошла ошибка при обновлении группы пользователей %s" - -#: rhodecode/controllers/admin/users_groups.py:250 -msgid "Successfully deleted user group" -msgstr "Группа пользователей успешно удалена" - -#: rhodecode/controllers/admin/users_groups.py:255 -msgid "An error occurred during deletion of user group" -msgstr "Произошла ошибка при удалении группы пользователей" - -#: rhodecode/controllers/admin/users_groups.py:274 -msgid "Target group cannot be the same" -msgstr "Целевая группа не может быть такой же" - -#: rhodecode/controllers/admin/users_groups.py:280 -msgid "User Group permissions updated" -msgstr "Привилегии группы пользователей обновлены" - -#: rhodecode/lib/auth.py:544 +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "Удален IP %s из белого списка пользователя" + +#: kallithea/lib/auth.py:748 #, python-format msgid "IP %s not allowed" msgstr "IP %s заблокирован" -#: rhodecode/lib/auth.py:593 +#: kallithea/lib/auth.py:809 msgid "You need to be a registered user to perform this action" -msgstr "Вы должны быть зарегистрированным пользователем, чтобы выполнить это действие" - -#: rhodecode/lib/auth.py:634 +msgstr "" +"Вы должны быть зарегистрированным пользователем, чтобы выполнить это " +"действие" + +#: kallithea/lib/auth.py:846 msgid "You need to be a signed in to view this page" msgstr "Страница доступна только авторизованным пользователям" -#: rhodecode/lib/diffs.py:66 +#: kallithea/lib/diffs.py:66 msgid "Binary file" msgstr "Двоичный файл" -#: rhodecode/lib/diffs.py:82 -msgid "" -"Changeset was too big and was cut off, use diff menu to display this diff" -msgstr "Набор изменения оказался слишком большими и был урезан, используйте меню сравнения для показа результата сравнения" - -#: rhodecode/lib/diffs.py:92 +#: kallithea/lib/diffs.py:82 +msgid "Changeset was too big and was cut off, use diff menu to display this diff" +msgstr "" +"Набор изменения оказался слишком большими и был урезан, используйте меню " +"сравнения для показа результата сравнения" + +#: kallithea/lib/diffs.py:92 msgid "No changes detected" msgstr "Изменений не обнаружено" -#: rhodecode/lib/helpers.py:539 -msgid "True" -msgstr "Истина" - -#: rhodecode/lib/helpers.py:542 -msgid "False" -msgstr "Ложь" - -#: rhodecode/lib/helpers.py:580 +#: kallithea/lib/helpers.py:598 #, python-format msgid "Deleted branch: %s" msgstr "Удалена ветка: %s" -#: rhodecode/lib/helpers.py:583 +#: kallithea/lib/helpers.py:601 #, python-format msgid "Created tag: %s" msgstr "Создан тег: %s" -#: rhodecode/lib/helpers.py:596 +#: kallithea/lib/helpers.py:614 msgid "Changeset not found" msgstr "Набор изменений не найден" -#: rhodecode/lib/helpers.py:646 +#: kallithea/lib/helpers.py:664 #, python-format msgid "Show all combined changesets %s->%s" -msgstr "" - -#: rhodecode/lib/helpers.py:652 +msgstr "Показать отличия вместе %s->%s" + +#: kallithea/lib/helpers.py:670 msgid "compare view" msgstr "сравнение" -#: rhodecode/lib/helpers.py:672 +#: kallithea/lib/helpers.py:690 msgid "and" msgstr "и" -#: rhodecode/lib/helpers.py:673 +#: kallithea/lib/helpers.py:691 #, python-format msgid "%s more" msgstr "на %s больше" -#: rhodecode/lib/helpers.py:674 -#: rhodecode/templates/changelog/changelog.html:53 +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 msgid "revisions" msgstr "версии" -#: rhodecode/lib/helpers.py:698 +#: kallithea/lib/helpers.py:716 #, python-format msgid "fork name %s" msgstr "имя форка %s" -#: rhodecode/lib/helpers.py:715 -#: rhodecode/templates/pullrequests/pullrequest_show.html:8 +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 #, python-format msgid "Pull request #%s" msgstr "Pull запрос #%s" -#: rhodecode/lib/helpers.py:725 +#: kallithea/lib/helpers.py:743 msgid "[deleted] repository" msgstr "[удален] репозиторий" -#: rhodecode/lib/helpers.py:727 rhodecode/lib/helpers.py:739 +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 msgid "[created] repository" msgstr "[создан] репозиторий" -#: rhodecode/lib/helpers.py:729 +#: kallithea/lib/helpers.py:747 msgid "[created] repository as fork" msgstr "[создан] репозиторий как форк" -#: rhodecode/lib/helpers.py:731 rhodecode/lib/helpers.py:741 +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 msgid "[forked] repository" msgstr "[форкнут] репозиторий" -#: rhodecode/lib/helpers.py:733 rhodecode/lib/helpers.py:743 +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 msgid "[updated] repository" msgstr "[обновлён] репозиторий" -#: rhodecode/lib/helpers.py:735 +#: kallithea/lib/helpers.py:753 msgid "[downloaded] archive from repository" msgstr "[загружен] архив из репозитория" -#: rhodecode/lib/helpers.py:737 +#: kallithea/lib/helpers.py:755 msgid "[delete] repository" msgstr "[удален] репозиторий" -#: rhodecode/lib/helpers.py:745 +#: kallithea/lib/helpers.py:763 msgid "[created] user" msgstr "[создан] пользователь" -#: rhodecode/lib/helpers.py:747 +#: kallithea/lib/helpers.py:765 msgid "[updated] user" msgstr "[обновлён] пользователь" -#: rhodecode/lib/helpers.py:749 +#: kallithea/lib/helpers.py:767 msgid "[created] user group" msgstr "[создана] группа пользователей" -#: rhodecode/lib/helpers.py:751 +#: kallithea/lib/helpers.py:769 msgid "[updated] user group" msgstr "[обновлена] группа пользователей" -#: rhodecode/lib/helpers.py:753 +#: kallithea/lib/helpers.py:771 msgid "[commented] on revision in repository" -msgstr "[комментировано] в версии в репозитории" - -#: rhodecode/lib/helpers.py:755 +msgstr "[комментарий] к ревизии в репозитории" + +#: kallithea/lib/helpers.py:773 msgid "[commented] on pull request for" msgstr "[прокомментировано] в запросе на внесение изменений для" -#: rhodecode/lib/helpers.py:757 +#: kallithea/lib/helpers.py:775 msgid "[closed] pull request for" -msgstr "[закрыт] Pull запрос" - -#: rhodecode/lib/helpers.py:759 +msgstr "[закрыт] Pull-request для" + +#: kallithea/lib/helpers.py:777 msgid "[pushed] into" msgstr "[отправлено] в" -#: rhodecode/lib/helpers.py:761 -msgid "[committed via RhodeCode] into repository" -msgstr "[commit с помощью RhodeCode] в репозитории" - -#: rhodecode/lib/helpers.py:763 +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "[внесены изменения с помощью Kallithea] в репозитории" + +#: kallithea/lib/helpers.py:781 msgid "[pulled from remote] into repository" -msgstr "[получено из удаленного] в репозитории" - -#: rhodecode/lib/helpers.py:765 +msgstr "[внесены изменения из удалённого репозитория] в репозиторий" + +#: kallithea/lib/helpers.py:783 msgid "[pulled] from" -msgstr "[получено] из" - -#: rhodecode/lib/helpers.py:767 +msgstr "[внесены изменения] из" + +#: kallithea/lib/helpers.py:785 msgid "[started following] repository" msgstr "[добавлен в наблюдения] репозиторий" -#: rhodecode/lib/helpers.py:769 +#: kallithea/lib/helpers.py:787 msgid "[stopped following] repository" msgstr "[удалён из наблюдения] репозиторий" -#: rhodecode/lib/helpers.py:1088 +#: kallithea/lib/helpers.py:1101 #, python-format msgid " and %s more" msgstr "и на %s больше" -#: rhodecode/lib/helpers.py:1092 +#: kallithea/lib/helpers.py:1105 msgid "No Files" msgstr "Файлов нет" -#: rhodecode/lib/helpers.py:1158 +#: kallithea/lib/helpers.py:1171 msgid "new file" msgstr "новый файл" -#: rhodecode/lib/helpers.py:1161 +#: kallithea/lib/helpers.py:1174 msgid "mod" msgstr "mod" -#: rhodecode/lib/helpers.py:1164 +#: kallithea/lib/helpers.py:1177 msgid "del" msgstr "удалить" -#: rhodecode/lib/helpers.py:1167 +#: kallithea/lib/helpers.py:1180 msgid "rename" msgstr "переименовать" -#: rhodecode/lib/helpers.py:1172 +#: kallithea/lib/helpers.py:1185 msgid "chmod" msgstr "chmod" -#: rhodecode/lib/helpers.py:1404 +#: kallithea/lib/helpers.py:1417 #, python-format msgid "" -"%s repository is not mapped to db perhaps it was created or renamed from the" -" filesystem please run the application again in order to rescan repositories" -msgstr "Репозитарий %s не отображен в базе данных; возможно, он был создан или переименован из файловой системы. Пожалуйста, перезапустите приложение для сканирования репозитариев." - -#: rhodecode/lib/unionrepo.py:193 -msgid "cannot create new union repository" -msgstr "не возможно создать объединённый репозитарий" - -#: rhodecode/lib/utils2.py:410 +"%s repository is not mapped to db perhaps it was created or renamed from " +"the filesystem please run the application again in order to rescan " +"repositories" +msgstr "" +"Репозиторий %s отсутствует в базе данных; возможно, он был создан или " +"переименован из файловой системы. Пожалуйста, перезапустите приложение " +"для сканирования репозиториев." + +#: kallithea/lib/utils2.py:415 #, python-format msgid "%d year" msgid_plural "%d years" @@ -1044,7 +1160,7 @@ msgstr[0] "%d год" msgstr[1] "%d лет" msgstr[2] "%d года" -#: rhodecode/lib/utils2.py:411 +#: kallithea/lib/utils2.py:416 #, python-format msgid "%d month" msgid_plural "%d months" @@ -1052,7 +1168,7 @@ msgstr[0] "%d месяц" msgstr[1] "%d месяца" msgstr[2] "%d месяцев" -#: rhodecode/lib/utils2.py:412 +#: kallithea/lib/utils2.py:417 #, python-format msgid "%d day" msgid_plural "%d days" @@ -1060,7 +1176,7 @@ msgstr[0] "%d день" msgstr[1] "%d дня" msgstr[2] "%d дней" -#: rhodecode/lib/utils2.py:413 +#: kallithea/lib/utils2.py:418 #, python-format msgid "%d hour" msgid_plural "%d hours" @@ -1068,7 +1184,7 @@ msgstr[0] "%d час" msgstr[1] "%d часов" msgstr[2] "%d часа" -#: rhodecode/lib/utils2.py:414 +#: kallithea/lib/utils2.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" @@ -1076,7 +1192,7 @@ msgstr[0] "%d минута" msgstr[1] "%d минут" msgstr[2] "%d минуты" -#: rhodecode/lib/utils2.py:415 +#: kallithea/lib/utils2.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" @@ -1084,833 +1200,1087 @@ msgstr[0] "%d секунды" msgstr[1] "%d секунды" msgstr[2] "%d секунды" -#: rhodecode/lib/utils2.py:431 +#: kallithea/lib/utils2.py:436 #, python-format msgid "in %s" msgstr "в %s" -#: rhodecode/lib/utils2.py:433 +#: kallithea/lib/utils2.py:438 #, python-format msgid "%s ago" msgstr "%s назад" -#: rhodecode/lib/utils2.py:435 +#: kallithea/lib/utils2.py:440 #, python-format msgid "in %s and %s" msgstr "в %s и %s" -#: rhodecode/lib/utils2.py:438 +#: kallithea/lib/utils2.py:443 #, python-format msgid "%s and %s ago" msgstr "%s и %s назад" -#: rhodecode/lib/utils2.py:441 +#: kallithea/lib/utils2.py:446 msgid "just now" msgstr "прямо сейчас" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1163 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1303 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1388 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1408 rhodecode/model/db.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 msgid "Repository no access" msgstr "Репозитарий - нет доступа" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1164 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1184 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1304 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1389 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1409 rhodecode/model/db.py:1414 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 msgid "Repository read access" msgstr "Репозитарий - доступ на чтение" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1165 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1185 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1305 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1390 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1410 rhodecode/model/db.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 msgid "Repository write access" msgstr "Репозитарий - доступ на запись" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1166 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1186 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1306 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1391 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1411 rhodecode/model/db.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 msgid "Repository admin access" msgstr "Репозитарий - администрирование" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1168 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 msgid "Repositories Group no access" msgstr "Группа Репозиториев - нет доступа" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1169 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1309 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 msgid "Repositories Group read access" msgstr "Группа Репозиториев - доступ на чтение" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1170 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1310 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 msgid "Repositories Group write access" msgstr "Группа Репозиториев - доступ на запись" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1171 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1311 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 msgid "Repositories Group admin access" msgstr "Группа Репозиториев - администрирование" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1173 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1193 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1313 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1398 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1406 rhodecode/model/db.py:1411 -msgid "RhodeCode Administrator" -msgstr "Администратор RhodeCode " - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1174 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1194 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1314 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1399 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1429 rhodecode/model/db.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" +msgstr "Администратор Kallithea " + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 msgid "Repository creation disabled" msgstr "Создание репозиториев отключено" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1175 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1195 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1315 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1400 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1430 rhodecode/model/db.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 msgid "Repository creation enabled" msgstr "Создание репозиториев включено" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1176 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1196 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1316 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1401 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1432 rhodecode/model/db.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 msgid "Repository forking disabled" msgstr "Возможность создавать форк репозитория отключена" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1177 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1197 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1317 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1402 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1433 rhodecode/model/db.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 msgid "Repository forking enabled" msgstr "Возможность создавать форк репозитория включена" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1178 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1318 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 msgid "Register disabled" msgstr "Регистрация отключена" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1319 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1404 -msgid "Register new user with RhodeCode with manual activation" -msgstr "Регистрация нового пользователя в RhodeCode с ручной активацией" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1202 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1407 -msgid "Register new user with RhodeCode with auto activation" -msgstr "Регистрация нового пользователя в RhodeCode с автоматической активацией" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1623 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1643 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1763 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1838 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1934 rhodecode/model/db.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" +msgstr "Регистрация нового пользователя в Kallithea с ручной активацией" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" +msgstr "Регистрация нового пользователя в Kallithea с автоматической активацией" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 msgid "Not Reviewed" msgstr "Не просмотрено" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1624 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1644 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1764 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1839 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1935 rhodecode/model/db.py:1940 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 msgid "Approved" msgstr "Одобрено" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1625 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1645 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1765 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1840 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1936 rhodecode/model/db.py:1941 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 msgid "Rejected" msgstr "Отклонено" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1626 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1646 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1766 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1841 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1937 rhodecode/model/db.py:1942 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 msgid "Under Review" msgstr "На рассмотрении" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1252 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1270 rhodecode/model/db.py:1275 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 msgid "top level" msgstr "верхний уровень" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1393 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1413 rhodecode/model/db.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 msgid "Repository group no access" msgstr "Группа Репозиториев - нет доступа" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1394 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1414 rhodecode/model/db.py:1419 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 msgid "Repository group read access" msgstr "Группа репозиториев - доступ на чтение" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1395 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1415 rhodecode/model/db.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 msgid "Repository group write access" msgstr "Группа репозиториев - доступ на запись" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1396 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1416 rhodecode/model/db.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 msgid "Repository group admin access" msgstr "Группа репозиториев - администрирование" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1418 rhodecode/model/db.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 msgid "User group no access" msgstr "Группа пользователей - нет доступа" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1419 rhodecode/model/db.py:1424 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 msgid "User group read access" msgstr "Группа пользователей - доступ на чтение" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1420 rhodecode/model/db.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 msgid "User group write access" msgstr "Группа пользователей - доступ на запись" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1421 rhodecode/model/db.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 msgid "User group admin access" msgstr "Группа пользователей - администрирование" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1423 rhodecode/model/db.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 msgid "Repository Group creation disabled" msgstr "Создание групп репозиториев отключено" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1424 rhodecode/model/db.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 msgid "Repository Group creation enabled" msgstr "Создание групп репозиториев включено" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1426 rhodecode/model/db.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 msgid "User Group creation disabled" msgstr "Создание групп пользователей отключено" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1427 rhodecode/model/db.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 msgid "User Group creation enabled" msgstr "Создание групп пользователей включено" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1435 rhodecode/model/db.py:1440 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 msgid "Registration disabled" msgstr "Регистрация отключена" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1436 rhodecode/model/db.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 msgid "User Registration with manual account activation" msgstr "Регистрация пользователя с ручной активацией учётной записи" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1437 rhodecode/model/db.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 msgid "User Registration with automatic account activation" msgstr "Регистрация пользователя с автоматической активацией" -#: rhodecode/model/comment.py:75 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:77 #, python-format msgid "on line %s" msgstr "на строке %s" -#: rhodecode/model/comment.py:220 +#: kallithea/model/comment.py:222 msgid "[Mention]" msgstr "[Упоминание]" -#: rhodecode/model/forms.py:43 +#: kallithea/model/forms.py:57 msgid "Please enter a login" msgstr "Пожалуйста, введите логин" -#: rhodecode/model/forms.py:44 +#: kallithea/model/forms.py:58 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "Введите значение длиной не менее %(min)i символов" -#: rhodecode/model/forms.py:52 +#: kallithea/model/forms.py:66 msgid "Please enter a password" msgstr "Пожалуйста, введите пароль" -#: rhodecode/model/forms.py:53 +#: kallithea/model/forms.py:67 #, python-format msgid "Enter %(min)i characters or more" msgstr "Введите не менее %(min)i символов" -#: rhodecode/model/notification.py:228 +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:231 #, python-format msgid "%(user)s commented on changeset at %(when)s" msgstr "%(user)s оставил комментарий к набору изменений %(when)s" -#: rhodecode/model/notification.py:229 +#: kallithea/model/notification.py:232 #, python-format msgid "%(user)s sent message at %(when)s" msgstr "%(user)s отправил сообщение %(when)s" -#: rhodecode/model/notification.py:230 +#: kallithea/model/notification.py:233 #, python-format msgid "%(user)s mentioned you at %(when)s" msgstr "%(user)s упомянул вас %(when)s" -#: rhodecode/model/notification.py:231 -#, python-format -msgid "%(user)s registered in RhodeCode at %(when)s" -msgstr "%(user)s зарегистрировался в RhodeCode %(when)s" - -#: rhodecode/model/notification.py:232 +#: kallithea/model/notification.py:234 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "%(user)s зарегистрировался в Kallithea %(when)s" + +#: kallithea/model/notification.py:235 #, python-format msgid "%(user)s opened new pull request at %(when)s" msgstr "%(user)s открыл новый pull request %(when)s" -#: rhodecode/model/notification.py:233 +#: kallithea/model/notification.py:236 #, python-format msgid "%(user)s commented on pull request at %(when)s" msgstr "%(user)s оставил комментарий к pull request %(when)s" -#: rhodecode/model/pull_request.py:98 +#: kallithea/model/pull_request.py:107 #, python-format msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" msgstr "%(user)s просит вас рассмотреть pull request #%(pr_id)s: %(pr_title)s" -#: rhodecode/model/scm.py:674 +#: kallithea/model/scm.py:810 msgid "latest tip" msgstr "последняя версия" -#: rhodecode/model/user.py:232 +#: kallithea/model/user.py:198 msgid "New user registration" msgstr "Регистрация нового пользователя" -#: rhodecode/model/user.py:257 rhodecode/model/user.py:281 +#: kallithea/model/user.py:222 kallithea/model/user.py:247 msgid "You can't Edit this user since it's crucial for entire application" -msgstr "Вы не можете редактировать пользователя, поскольку это критично для работы всего приложения" - -#: rhodecode/model/user.py:303 +msgstr "" +"Вы не можете редактировать пользователя, поскольку это критично для " +"работы всего приложения" + +#: kallithea/model/user.py:270 msgid "You can't remove this user since it's crucial for entire application" -msgstr "Вы не можете удалить пользователя, поскольку это критично для работы всего приложения" - -#: rhodecode/model/user.py:309 +msgstr "" +"Вы не можете удалить пользователя, поскольку это критично для работы " +"всего приложения" + +#: kallithea/model/user.py:276 #, python-format msgid "" -"user \"%s\" still owns %s repositories and cannot be removed. Switch owners " -"or remove those repositories. %s" -msgstr "пользователь \"%s\" является владельцем репозиториев %s и поэтому не может быть удалён. Смените владельца или удалите данные репозитории. %s" - -#: rhodecode/model/user.py:334 +"user \"%s\" still owns %s repositories and cannot be removed. Switch " +"owners or remove those repositories. %s" +msgstr "" +"пользователь \"%s\" является владельцем репозиториев %s и поэтому не " +"может быть удалён. Смените владельца или удалите данные репозитории. %s" + +#: kallithea/model/user.py:304 msgid "Password reset link" msgstr "Ссылка сброса пароля" -#: rhodecode/model/user.py:366 +#: kallithea/model/user.py:333 msgid "Your new password" msgstr "Ваш новый пароль" -#: rhodecode/model/user.py:367 -#, python-format -msgid "Your new RhodeCode password:%s" -msgstr "Ваш новый пароль от RhodeCode: %s" - -#: rhodecode/model/validators.py:38 rhodecode/model/validators.py:39 +#: kallithea/model/user.py:334 +#, python-format +msgid "Your new Kallithea password:%s" +msgstr "Ваш новый пароль от Kallithea: %s" + +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 msgid "Value cannot be an empty list" msgstr "Значение не может быть пустым списком" -#: rhodecode/model/validators.py:85 +#: kallithea/model/validators.py:120 #, python-format msgid "Username \"%(username)s\" already exists" msgstr "Пользователь с именем \"%(username)s\" уже существует" -#: rhodecode/model/validators.py:87 +#: kallithea/model/validators.py:122 #, python-format msgid "Username \"%(username)s\" is forbidden" msgstr "Имя \"%(username)s\" отклонено" -#: rhodecode/model/validators.py:89 +#: kallithea/model/validators.py:124 msgid "" -"Username may only contain alphanumeric characters underscores, periods or " -"dashes and must begin with alphanumeric character or underscore" -msgstr "Имя пользователя может содержать только буквы, цифры, символы подчеркивания, точки и тире; а так же должно начинаться с буквы, цифры либо с символа подчеркивания" - -#: rhodecode/model/validators.py:117 +"Username may only contain alphanumeric characters underscores, periods or" +" dashes and must begin with alphanumeric character or underscore" +msgstr "" +"Имя пользователя может содержать только буквы, цифры, символы " +"подчеркивания, точки и тире; а так же должно начинаться с буквы, цифры " +"либо с символа подчеркивания" + +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:158 #, python-format msgid "Username %(username)s is not valid" msgstr "Имя \"%(username)s\" недопустимо" -#: rhodecode/model/validators.py:136 +#: kallithea/model/validators.py:177 msgid "Invalid user group name" msgstr "Неверное имя группы пользователей" -#: rhodecode/model/validators.py:137 +#: kallithea/model/validators.py:178 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "Группа пользователей \"%(usergroup)s\" уже существует" -#: rhodecode/model/validators.py:139 +#: kallithea/model/validators.py:180 msgid "" "user group name may only contain alphanumeric characters underscores, " "periods or dashes and must begin with alphanumeric character" -msgstr "имя группы пользователей может содержать только буквы, цифры, символы подчеркивания, точки и тире; а так же должно начинаться с буквы или цифры" - -#: rhodecode/model/validators.py:177 +msgstr "" +"имя группы пользователей может содержать только буквы, цифры, символы " +"подчеркивания, точки и тире; а так же должно начинаться с буквы или цифры" + +#: kallithea/model/validators.py:218 msgid "Cannot assign this group as parent" msgstr "Невозможно использовать эту группу как родителя" -#: rhodecode/model/validators.py:178 +#: kallithea/model/validators.py:219 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "Группа \"%(group_name)s\" уже существует" -#: rhodecode/model/validators.py:180 +#: kallithea/model/validators.py:221 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "Репозитарий с именем \"%(group_name)s\" уже существует" -#: rhodecode/model/validators.py:238 +#: kallithea/model/validators.py:279 msgid "Invalid characters (non-ascii) in password" msgstr "Недопустимые символы (не ascii) в пароле" -#: rhodecode/model/validators.py:253 +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 msgid "Passwords do not match" msgstr "Пароли не совпадают" -#: rhodecode/model/validators.py:270 +#: kallithea/model/validators.py:327 msgid "invalid password" msgstr "неверный пароль" -#: rhodecode/model/validators.py:271 +#: kallithea/model/validators.py:328 msgid "invalid user name" msgstr "неверное имя пользователя" -#: rhodecode/model/validators.py:272 +#: kallithea/model/validators.py:329 msgid "Your account is disabled" msgstr "Ваш аккаунт выключен" -#: rhodecode/model/validators.py:316 +#: kallithea/model/validators.py:373 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "Имя репозитория %(repo)s запрещено" -#: rhodecode/model/validators.py:318 +#: kallithea/model/validators.py:375 #, python-format msgid "Repository named %(repo)s already exists" msgstr "Репозитарий %(repo)s уже существует" -#: rhodecode/model/validators.py:319 +#: kallithea/model/validators.py:376 #, python-format msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" msgstr "Репозитарий \"%(repo)s\" уже существует в группе \"%(group)s\"" -#: rhodecode/model/validators.py:321 +#: kallithea/model/validators.py:378 #, python-format msgid "Repository group with name \"%(repo)s\" already exists" msgstr "Группа репозиториев \"%(repo)s\" уже существует" -#: rhodecode/model/validators.py:438 +#: kallithea/model/validators.py:493 msgid "invalid clone url" msgstr "неверный URL" -#: rhodecode/model/validators.py:439 +#: kallithea/model/validators.py:494 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" -msgstr "Неверная ссылка клонирования, предоставьте действительную ссылку для клонирования - http(s)/svn+http(s)." - -#: rhodecode/model/validators.py:464 +msgstr "" +"Неверная ссылка клонирования, предоставьте действительную ссылку для " +"клонирования - http(s)/svn+http(s)." + +#: kallithea/model/validators.py:519 msgid "Fork have to be the same type as parent" msgstr "Тип форка будет совпадать с родительским" -#: rhodecode/model/validators.py:479 +#: kallithea/model/validators.py:534 msgid "You don't have permissions to create repository in this group" -msgstr "У вас нет прав создания репозиториев в этой группе" - -#: rhodecode/model/validators.py:481 +msgstr "У вас недостаточно прав для создания репозиториев в этой группе" + +#: kallithea/model/validators.py:536 msgid "no permission to create repository in root location" -msgstr "нет прав создания репозиториев в корне" - -#: rhodecode/model/validators.py:518 +msgstr "недостаточно прав для создания репозитория в корневом каталоге" + +#: kallithea/model/validators.py:585 msgid "You don't have permissions to create a group in this location" -msgstr "У Вас нет прав создавать группу в этом месте" - -#: rhodecode/model/validators.py:559 +msgstr "У Вас недостаточно привилегий для создания группы в этом месте" + +#: kallithea/model/validators.py:626 msgid "This username or user group name is not valid" msgstr "Данное имя пользователя или группы пользователей недопустимо" -#: rhodecode/model/validators.py:652 +#: kallithea/model/validators.py:719 msgid "This is not a valid path" msgstr "Этот путь ошибочен" -#: rhodecode/model/validators.py:667 +#: kallithea/model/validators.py:734 msgid "This e-mail address is already taken" msgstr "Этот E-mail уже занят" -#: rhodecode/model/validators.py:687 +#: kallithea/model/validators.py:754 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "\"%(email)s\" не существует" -#: rhodecode/model/validators.py:724 +#: kallithea/model/validators.py:791 msgid "" -"The LDAP Login attribute of the CN must be specified - this is the name of " -"the attribute that is equivalent to \"username\"" -msgstr "Для входа по LDAP должно быть указано значение аттрибута CN - это эквивалент имени пользователя" - -#: rhodecode/model/validators.py:737 +"The LDAP Login attribute of the CN must be specified - this is the name " +"of the attribute that is equivalent to \"username\"" +msgstr "" +"Для входа по LDAP должно быть указано значение аттрибута CN - это " +"эквивалент имени пользователя" + +#: kallithea/model/validators.py:804 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" msgstr "" - -#: rhodecode/model/validators.py:769 +"Ревизии %(revs)s уже включены в pull-request или имеют установленный " +"статус" + +#: kallithea/model/validators.py:836 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "Пожалуйста, введите существующий IPv4 или IpV6 адре" -#: rhodecode/model/validators.py:770 -#, python-format -msgid "" -"The network size (bits) must be within the range of 0-32 (not %(bits)r)" -msgstr "Значение маски подсети должно быть в пределах от 0 до 32 (%(bits)r - неверно)" - -#: rhodecode/model/validators.py:803 +#: kallithea/model/validators.py:837 +#, python-format +msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" +msgstr "" +"Значение маски подсети должно быть в пределах от 0 до 32 (%(bits)r - " +"неверно)" + +#: kallithea/model/validators.py:870 msgid "Key name can only consist of letters, underscore, dash or numbers" -msgstr "Ключевое имя может только состоять из букв, символа подчеркивания, тире или чисел" - -#: rhodecode/model/validators.py:817 +msgstr "" +"Ключевое имя может только состоять из букв, символа подчеркивания, тире " +"или чисел" + +#: kallithea/model/validators.py:884 msgid "Filename cannot be inside a directory" msgstr "Файла нет в каталоге" -#: rhodecode/templates/index.html:5 +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" +msgstr "" + +#: kallithea/templates/index.html:5 msgid "Dashboard" msgstr "Панель управления" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/repo_switcher_list.html:4 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/users/user_edit_my_account.html:31 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/bookmarks/bookmarks.html:9 -#: rhodecode/templates/branches/branches.html:9 -#: rhodecode/templates/journal/journal.html:9 -#: rhodecode/templates/journal/journal.html:46 -#: rhodecode/templates/journal/journal.html:47 -#: rhodecode/templates/tags/tags.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 msgid "quick filter..." -msgstr "быстрый фильтр..." - -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/admin/repos/repos.html:9 +msgstr "фильтр..." + +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 msgid "repositories" msgstr "репозитарии" -#: rhodecode/templates/index_base.html:13 -#: rhodecode/templates/index_base.html:18 -#: rhodecode/templates/admin/repos/repo_add.html:5 -#: rhodecode/templates/admin/repos/repos.html:22 -msgid "Add repository" +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" msgstr "Добавить репозиторий" -#: rhodecode/templates/index_base.html:15 -#: rhodecode/templates/index_base.html:20 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:31 -msgid "Add group" -msgstr "Добавить группу" - -#: rhodecode/templates/index_base.html:27 -msgid "Edit group" -msgstr "Редактировать группу" - -#: rhodecode/templates/index_base.html:27 +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "Добавить группу репозиториев" + +#: kallithea/templates/index_base.html:32 msgid "You have admin right to this group, and can edit it" msgstr "Вы имеете администраторские права на эту группу и можете редактировать её" -#: rhodecode/templates/index_base.html:40 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:33 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:38 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:43 -#: rhodecode/templates/admin/users_groups/users_group_add.html:32 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 -#: rhodecode/templates/admin/users_groups/users_groups.html:37 -msgid "Group name" +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "Изменить группу репозиториев" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" msgstr "Имя группы" -#: rhodecode/templates/index_base.html:41 -#: rhodecode/templates/index_base.html:123 -#: rhodecode/templates/admin/repos/repo_add_base.html:56 -#: rhodecode/templates/admin/repos/repo_edit.html:68 -#: rhodecode/templates/admin/repos/repos.html:75 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:42 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:47 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:44 -#: rhodecode/templates/email_templates/changeset_comment.html:9 -#: rhodecode/templates/email_templates/pull_request.html:9 -#: rhodecode/templates/forks/fork.html:56 -#: rhodecode/templates/pullrequests/pullrequest.html:43 -#: rhodecode/templates/pullrequests/pullrequest_show.html:81 -#: rhodecode/templates/summary/summary.html:106 +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 msgid "Description" msgstr "Описание" -#: rhodecode/templates/index_base.html:51 -#: rhodecode/templates/admin/permissions/permissions.html:55 -#: rhodecode/templates/admin/repos/repo_add_base.html:29 -#: rhodecode/templates/admin/repos/repo_edit.html:50 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:57 -#: rhodecode/templates/forks/fork.html:47 -msgid "Repository group" -msgstr "Группа репозиториев" - -#: rhodecode/templates/index_base.html:121 -#: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit.html:32 -#: rhodecode/templates/admin/repos/repos.html:73 -#: rhodecode/templates/admin/users/user_edit_my_account.html:172 -#: rhodecode/templates/base/perms_summary.html:37 -#: rhodecode/templates/bookmarks/bookmarks.html:48 -#: rhodecode/templates/bookmarks/bookmarks_data.html:6 -#: rhodecode/templates/branches/branches.html:47 -#: rhodecode/templates/branches/branches_data.html:6 -#: rhodecode/templates/files/files_browser.html:47 -#: rhodecode/templates/journal/journal.html:193 -#: rhodecode/templates/journal/journal.html:283 -#: rhodecode/templates/summary/summary.html:55 -#: rhodecode/templates/summary/summary.html:124 -#: rhodecode/templates/tags/tags.html:48 -#: rhodecode/templates/tags/tags_data.html:6 +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 msgid "Name" msgstr "Имя" -#: rhodecode/templates/index_base.html:124 +#: kallithea/templates/index_base.html:129 msgid "Last Change" msgstr "Последнее изменение" -#: rhodecode/templates/index_base.html:126 -#: rhodecode/templates/admin/repos/repos.html:76 -#: rhodecode/templates/admin/users/user_edit_my_account.html:174 -#: rhodecode/templates/journal/journal.html:195 -#: rhodecode/templates/journal/journal.html:285 +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 msgid "Tip" -msgstr "Подсказка" - -#: rhodecode/templates/index_base.html:128 -#: rhodecode/templates/admin/repos/repo_edit.html:114 -#: rhodecode/templates/admin/repos/repos.html:78 +msgstr "Состояние" + +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 msgid "Owner" msgstr "Владелец" -#: rhodecode/templates/index_base.html:136 -#: rhodecode/templates/admin/repos/repos.html:86 -#: rhodecode/templates/admin/users/user_edit_my_account.html:183 -#: rhodecode/templates/admin/users/users.html:107 -#: rhodecode/templates/bookmarks/bookmarks.html:74 -#: rhodecode/templates/branches/branches.html:73 -#: rhodecode/templates/journal/journal.html:204 -#: rhodecode/templates/journal/journal.html:294 -#: rhodecode/templates/tags/tags.html:74 +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 msgid "Click to sort ascending" msgstr "По возрастанию" -#: rhodecode/templates/index_base.html:137 -#: rhodecode/templates/admin/repos/repos.html:87 -#: rhodecode/templates/admin/users/user_edit_my_account.html:184 -#: rhodecode/templates/admin/users/users.html:108 -#: rhodecode/templates/bookmarks/bookmarks.html:75 -#: rhodecode/templates/branches/branches.html:74 -#: rhodecode/templates/journal/journal.html:205 -#: rhodecode/templates/journal/journal.html:295 -#: rhodecode/templates/tags/tags.html:75 +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 msgid "Click to sort descending" msgstr "По убыванию" -#: rhodecode/templates/index_base.html:138 +#: kallithea/templates/index_base.html:143 msgid "No repositories found." msgstr "Репозитарии не найдены." -#: rhodecode/templates/index_base.html:139 -#: rhodecode/templates/admin/repos/repos.html:89 -#: rhodecode/templates/admin/users/user_edit_my_account.html:186 -#: rhodecode/templates/admin/users/users.html:110 -#: rhodecode/templates/bookmarks/bookmarks.html:77 -#: rhodecode/templates/branches/branches.html:76 -#: rhodecode/templates/journal/journal.html:207 -#: rhodecode/templates/journal/journal.html:297 -#: rhodecode/templates/tags/tags.html:77 +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 msgid "Data error." msgstr "Ошибка данных." -#: rhodecode/templates/index_base.html:140 -#: rhodecode/templates/admin/repos/repos.html:90 -#: rhodecode/templates/admin/users/user_edit_my_account.html:58 -#: rhodecode/templates/admin/users/user_edit_my_account.html:187 -#: rhodecode/templates/admin/users/users.html:111 -#: rhodecode/templates/bookmarks/bookmarks.html:78 -#: rhodecode/templates/branches/branches.html:77 -#: rhodecode/templates/journal/journal.html:208 -#: rhodecode/templates/journal/journal.html:298 -#: rhodecode/templates/tags/tags.html:78 +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 msgid "Loading..." msgstr "Загрузка..." -#: rhodecode/templates/login.html:5 rhodecode/templates/base/base.html:239 +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 msgid "Log In" msgstr "Войти" -#: rhodecode/templates/login.html:21 +#: kallithea/templates/login.html:30 #, python-format msgid "Log In to %s" msgstr "Войти в %s" -#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20 -#: rhodecode/templates/admin/admin_log.html:5 -#: rhodecode/templates/admin/users/user_add.html:32 -#: rhodecode/templates/admin/users/user_edit.html:57 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:31 -#: rhodecode/templates/admin/users/users.html:77 -#: rhodecode/templates/base/base.html:215 -#: rhodecode/templates/summary/summary.html:123 +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 msgid "Username" msgstr "Имя пользователя" -#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29 -#: rhodecode/templates/admin/ldap/ldap.html:46 -#: rhodecode/templates/admin/users/user_add.html:41 -#: rhodecode/templates/base/base.html:224 +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 msgid "Password" msgstr "Пароль" -#: rhodecode/templates/login.html:50 +#: kallithea/templates/login.html:62 msgid "Remember me" msgstr "Запомнить" -#: rhodecode/templates/login.html:54 +#: kallithea/templates/login.html:66 msgid "Sign In" msgstr "Войти" -#: rhodecode/templates/login.html:60 +#: kallithea/templates/login.html:72 msgid "Forgot your password ?" msgstr "Забыли пароль?" -#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:235 +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 msgid "Don't have an account ?" msgstr "Нет аккаунта?" -#: rhodecode/templates/password_reset.html:5 +#: kallithea/templates/password_reset.html:5 msgid "Password Reset" msgstr "Сброс пароля" -#: rhodecode/templates/password_reset.html:11 -msgid "Reset your password to" -msgstr "Сбросить пароль на" - -#: rhodecode/templates/password_reset.html:21 -msgid "Email address" +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" msgstr "Почтовый адрес" -#: rhodecode/templates/password_reset.html:30 -msgid "Reset my password" -msgstr "Сбросить пароль" - -#: rhodecode/templates/password_reset.html:31 +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "" + +#: kallithea/templates/password_reset.html:64 msgid "Password reset link will be send to matching email address" msgstr "Ссылка для сброса пароля была отправлена на соответствующий E-mail" -#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74 +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 msgid "Sign Up" msgstr "Вступить" -#: rhodecode/templates/register.html:11 -msgid "Sign Up to" -msgstr "Вступить в" - -#: rhodecode/templates/register.html:38 +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:58 msgid "Re-enter password" msgstr "Повторите пароль" -#: rhodecode/templates/register.html:47 -#: rhodecode/templates/admin/users/user_add.html:59 -#: rhodecode/templates/admin/users/user_edit.html:97 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:62 +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 msgid "First Name" msgstr "Имя" -#: rhodecode/templates/register.html:56 -#: rhodecode/templates/admin/users/user_add.html:68 -#: rhodecode/templates/admin/users/user_edit.html:106 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:71 +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 msgid "Last Name" msgstr "Фамилия" -#: rhodecode/templates/register.html:65 -#: rhodecode/templates/admin/users/user_add.html:77 -#: rhodecode/templates/admin/users/user_edit.html:115 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:80 -#: rhodecode/templates/summary/summary.html:125 +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 msgid "Email" msgstr "E-mail" -#: rhodecode/templates/register.html:76 +#: kallithea/templates/register.html:108 msgid "Your account will be activated right after registration" msgstr "Ваш аккаунт будет активирован сразу после регистрации" -#: rhodecode/templates/register.html:78 +#: kallithea/templates/register.html:110 msgid "Your account must wait for activation by administrator" msgstr "Ваш аккаунт ожидает модерации" -#: rhodecode/templates/repo_switcher_list.html:10 -#: rhodecode/templates/admin/defaults/defaults.html:44 -#: rhodecode/templates/admin/repos/repo_add_base.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:78 -#: rhodecode/templates/data_table/_dt_elements.html:61 -#: rhodecode/templates/summary/summary.html:77 -msgid "Private repository" -msgstr "Частный репозиторий" - -#: rhodecode/templates/repo_switcher_list.html:12 -#: rhodecode/templates/data_table/_dt_elements.html:63 -#: rhodecode/templates/summary/summary.html:79 -msgid "Public repository" -msgstr "Публичный репозиторий" - -#: rhodecode/templates/switch_to_list.html:10 -#: rhodecode/templates/branches/branches_data.html:57 +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 msgid "There are no branches yet" msgstr "Ветки ещё не созданы" -#: rhodecode/templates/switch_to_list.html:22 -#: rhodecode/templates/tags/tags_data.html:38 +#: kallithea/templates/switch_to_list.html:16 +msgid "Closed Branches" +msgstr "Закрытые ветки" + +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 msgid "There are no tags yet" msgstr "Метки отсутсвуют" -#: rhodecode/templates/switch_to_list.html:35 -#: rhodecode/templates/bookmarks/bookmarks_data.html:37 +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 msgid "There are no bookmarks yet" msgstr "Закладок ещё нет" -#: rhodecode/templates/admin/admin.html:5 -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/base/base.html:73 +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 msgid "Admin journal" msgstr "Журнал администратора" -#: rhodecode/templates/admin/admin.html:10 +#: kallithea/templates/admin/admin.html:13 msgid "journal filter..." msgstr "Фильтр журнала..." -#: rhodecode/templates/admin/admin.html:12 -#: rhodecode/templates/journal/journal.html:11 +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 msgid "filter" -msgstr "фильтр" - -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/journal/journal.html:12 +msgstr "Отфильтровать" + +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 #, python-format msgid "%s entry" msgid_plural "%s entries" @@ -1918,909 +2288,866 @@ msgstr[0] "%s запись" msgstr[1] "%s записей" msgstr[2] "%s записи" -#: rhodecode/templates/admin/admin_log.html:6 -#: rhodecode/templates/admin/repos/repos.html:79 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46 -#: rhodecode/templates/admin/users/user_edit_my_account.html:176 -#: rhodecode/templates/admin/users/users.html:87 -#: rhodecode/templates/admin/users_groups/users_groups.html:40 -#: rhodecode/templates/journal/journal.html:197 -#: rhodecode/templates/journal/journal.html:287 +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 msgid "Action" msgstr "Действие" -#: rhodecode/templates/admin/admin_log.html:7 -#: rhodecode/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" msgstr "Репозитарий" -#: rhodecode/templates/admin/admin_log.html:8 -#: rhodecode/templates/bookmarks/bookmarks.html:49 -#: rhodecode/templates/bookmarks/bookmarks_data.html:7 -#: rhodecode/templates/branches/branches.html:48 -#: rhodecode/templates/branches/branches_data.html:7 -#: rhodecode/templates/tags/tags.html:49 -#: rhodecode/templates/tags/tags_data.html:7 +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 msgid "Date" msgstr "Дата" -#: rhodecode/templates/admin/admin_log.html:9 +#: kallithea/templates/admin/admin_log.html:9 msgid "From IP" msgstr "С IP" -#: rhodecode/templates/admin/admin_log.html:63 +#: kallithea/templates/admin/admin_log.html:63 msgid "No actions yet" msgstr "Действия ещё не производились" -#: rhodecode/templates/admin/defaults/defaults.html:5 -#: rhodecode/templates/admin/defaults/defaults.html:25 +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "Настройки аутентификации" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "Аутентификация" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "Плагины аутентификации" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "Включенные плагины" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "" +"Comma separated list of plugins. Order of plugins is also order in which " +"Kallithea will try to authenticate user" +msgstr "" +"Список плагинов, разделенных запятой. Kallithea будет пробовать " +"аутентифицировать пользователя в порядке указания плагинов." + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "Доступные встроенные плагины" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "Сохранить" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "Плагин" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 msgid "Repositories defaults" msgstr " Значения по умолчанию" -#: rhodecode/templates/admin/defaults/defaults.html:11 -#: rhodecode/templates/base/base.html:80 +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 msgid "Defaults" msgstr "Значения по умолчанию" -#: rhodecode/templates/admin/defaults/defaults.html:35 -#: rhodecode/templates/admin/repos/repo_add_base.html:38 +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 msgid "Type" msgstr "Тип" -#: rhodecode/templates/admin/defaults/defaults.html:48 -#: rhodecode/templates/admin/repos/repo_add_base.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:82 -#: rhodecode/templates/forks/fork.html:69 +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "Приватный репозиторий" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 msgid "" "Private repositories are only visible to people explicitly added as " "collaborators." msgstr "Приватные репозитории видны только их участникам" -#: rhodecode/templates/admin/defaults/defaults.html:55 -#: rhodecode/templates/admin/repos/repo_edit.html:87 +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 msgid "Enable statistics" msgstr "Включить статистику." -#: rhodecode/templates/admin/defaults/defaults.html:59 -#: rhodecode/templates/admin/repos/repo_edit.html:91 +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." -msgstr "Включить окно статистики на странице summary." - -#: rhodecode/templates/admin/defaults/defaults.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:96 +msgstr "Включить окно статистики на странице 'Общие сведения'." + +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 msgid "Enable downloads" msgstr "Включить скачивание" -#: rhodecode/templates/admin/defaults/defaults.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:100 +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." -msgstr "Включить меню скачивания на странице summary." - -#: rhodecode/templates/admin/defaults/defaults.html:75 -#: rhodecode/templates/admin/repos/repo_edit.html:105 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:64 +msgstr "Включить меню скачивания на странице 'Общие сведения'." + +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 msgid "Enable locking" msgstr "Включить блокирование" -#: rhodecode/templates/admin/defaults/defaults.html:79 -#: rhodecode/templates/admin/repos/repo_edit.html:109 +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 msgid "Enable lock-by-pulling on repository." -msgstr "" - -#: rhodecode/templates/admin/defaults/defaults.html:84 -#: rhodecode/templates/admin/ldap/ldap.html:89 -#: rhodecode/templates/admin/permissions/permissions.html:122 -#: rhodecode/templates/admin/repos/repo_edit.html:141 -#: rhodecode/templates/admin/repos/repo_edit.html:166 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:72 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:96 -#: rhodecode/templates/admin/settings/hooks.html:73 -#: rhodecode/templates/admin/users/user_add.html:94 -#: rhodecode/templates/admin/users/user_edit.html:140 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:88 -#: rhodecode/templates/admin/users_groups/users_group_add.html:49 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:143 -#: rhodecode/templates/base/default_perms_box.html:53 -msgid "Save" -msgstr "Сохранить" - -#: rhodecode/templates/admin/gists/index.html:5 -#: rhodecode/templates/base/base.html:299 -msgid "Gists" -msgstr "Gist" - -#: rhodecode/templates/admin/gists/index.html:10 +msgstr "Включить lock-by-pulling для репозитория" + +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "" +"Gist was update since you started editing. Copy your changes and click " +"%(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "Описание..." + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "Истекает" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "никогда" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "plain" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "Отмена" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 #, python-format msgid "Private Gists for user %s" msgstr "Приватная запись Gist для пользователя %s" -#: rhodecode/templates/admin/gists/index.html:12 +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 #, python-format msgid "Public Gists for user %s" msgstr "Публичная запись Gist для пользователя %s" -#: rhodecode/templates/admin/gists/index.html:14 +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 msgid "Public Gists" msgstr "Публичные записи Gist" -#: rhodecode/templates/admin/gists/index.html:31 -#: rhodecode/templates/admin/gists/show.html:24 -#: rhodecode/templates/base/base.html:302 -msgid "Create new gist" -msgstr "Создать новую запись" - -#: rhodecode/templates/admin/gists/index.html:48 +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 msgid "Created" msgstr "Создано" -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/index.html:53 -#: rhodecode/templates/admin/gists/show.html:43 -#: rhodecode/templates/admin/gists/show.html:45 -msgid "Expires" -msgstr "Истекает" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/show.html:43 -msgid "never" -msgstr "никогда" - -#: rhodecode/templates/admin/gists/index.html:68 +#: kallithea/templates/admin/gists/index.html:77 msgid "There are no gists yet" msgstr "Записи Gist отсутствуют" -#: rhodecode/templates/admin/gists/new.html:5 -#: rhodecode/templates/admin/gists/new.html:16 -msgid "New gist" -msgstr "Новая запись" - -#: rhodecode/templates/admin/gists/new.html:37 -msgid "Gist description ..." -msgstr "Описание..." - -#: rhodecode/templates/admin/gists/new.html:52 -msgid "Create private gist" -msgstr "Создать приватную запись" - -#: rhodecode/templates/admin/gists/new.html:53 -msgid "Create public gist" -msgstr "Создать публичную запись" - -#: rhodecode/templates/admin/gists/new.html:54 -#: rhodecode/templates/admin/permissions/permissions.html:123 -#: rhodecode/templates/admin/permissions/permissions.html:185 -#: rhodecode/templates/admin/repos/repo_edit.html:142 -#: rhodecode/templates/admin/repos/repo_edit.html:167 -#: rhodecode/templates/admin/repos/repo_edit.html:381 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:97 -#: rhodecode/templates/admin/settings/settings.html:115 -#: rhodecode/templates/admin/settings/settings.html:196 -#: rhodecode/templates/admin/settings/settings.html:288 -#: rhodecode/templates/admin/users/user_edit.html:141 -#: rhodecode/templates/admin/users/user_edit.html:198 -#: rhodecode/templates/admin/users/user_edit.html:246 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:89 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:144 -#: rhodecode/templates/base/default_perms_box.html:54 -#: rhodecode/templates/files/files_add.html:80 -#: rhodecode/templates/files/files_edit.html:66 -#: rhodecode/templates/pullrequests/pullrequest.html:86 +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 msgid "Reset" msgstr "Сброс" -#: rhodecode/templates/admin/gists/show.html:5 -msgid "gist" -msgstr "gist" - -#: rhodecode/templates/admin/gists/show.html:9 +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 msgid "Gist" msgstr "Gist" -#: rhodecode/templates/admin/gists/show.html:36 -msgid "Public gist" -msgstr "Публичная запись gist" - -#: rhodecode/templates/admin/gists/show.html:38 -msgid "Private gist" -msgstr "Приватная запись gist" - -#: rhodecode/templates/admin/gists/show.html:54 -#: rhodecode/templates/admin/repos/repo_edit.html:299 -#: rhodecode/templates/changeset/changeset_file_comment.html:40 +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "URL" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 msgid "Delete" msgstr "Удалить" -#: rhodecode/templates/admin/gists/show.html:54 -msgid "Confirm to delete this gist" -msgstr "Подтвердите удаление записи" - -#: rhodecode/templates/admin/gists/show.html:63 -#: rhodecode/templates/admin/gists/show.html:84 -#: rhodecode/templates/files/files_edit.html:48 -#: rhodecode/templates/files/files_source.html:25 -#: rhodecode/templates/files/files_source.html:55 -msgid "Show as raw" -msgstr "Показать без форматирования" - -#: rhodecode/templates/admin/gists/show.html:71 +#: kallithea/templates/admin/gists/show.html:59 +msgid "Confirm to delete this Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "Редактировать" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:76 msgid "created" msgstr "создал" -#: rhodecode/templates/admin/ldap/ldap.html:5 -msgid "LDAP administration" -msgstr "администрирование LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:11 -#: rhodecode/templates/admin/users/users.html:86 -#: rhodecode/templates/base/base.html:79 -msgid "LDAP" -msgstr "LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:28 -msgid "Connection settings" -msgstr "Настройки подключения" - -#: rhodecode/templates/admin/ldap/ldap.html:30 -msgid "Enable LDAP" -msgstr "Включить LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:34 -msgid "Host" -msgstr "Хост" - -#: rhodecode/templates/admin/ldap/ldap.html:38 -msgid "Port" -msgstr "Порт" - -#: rhodecode/templates/admin/ldap/ldap.html:42 -msgid "Account" -msgstr "Аккаунт" - -#: rhodecode/templates/admin/ldap/ldap.html:50 -msgid "Connection security" -msgstr "Безопасность соединения" - -#: rhodecode/templates/admin/ldap/ldap.html:54 -msgid "Certificate Checks" -msgstr "Проверки сертификатов" - -#: rhodecode/templates/admin/ldap/ldap.html:57 -msgid "Search settings" -msgstr "Настройки поиска" - -#: rhodecode/templates/admin/ldap/ldap.html:59 -msgid "Base DN" -msgstr "Base DN" - -#: rhodecode/templates/admin/ldap/ldap.html:63 -msgid "LDAP Filter" -msgstr "Фильтр LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:67 -msgid "LDAP Search Scope" -msgstr "Область поиска LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:70 -msgid "Attribute mappings" -msgstr "Маппинги атрибутов" - -#: rhodecode/templates/admin/ldap/ldap.html:72 -msgid "Login Attribute" -msgstr "Атрибут \"Логин\"" - -#: rhodecode/templates/admin/ldap/ldap.html:76 -msgid "First Name Attribute" -msgstr "Атрибут \"Имя\"" - -#: rhodecode/templates/admin/ldap/ldap.html:80 -msgid "Last Name Attribute" -msgstr "Атрибут \"Фамилия\"" - -#: rhodecode/templates/admin/ldap/ldap.html:84 -msgid "E-mail Attribute" -msgstr "Атрибут \"E-mail\"" - -#: rhodecode/templates/admin/notifications/notifications.html:5 -#: rhodecode/templates/admin/notifications/notifications.html:9 +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "Показать без форматирования" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "Мой аккаунт" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" +msgstr "Мой Аккаунт" + +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "Профиль" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "Мои Email-ы" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "Мои репозитории" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "Просмотрено" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "Pull-request'ы" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "Мои привилегии" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "Добавить" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "Основной" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "удалить" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "Подтвердите удаление E-mail: %s" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "Дополнительных Email не указано" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "Новый E-mail" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "Новый пароль" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "Измените аватар через сайт" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "Используется" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "Аватары отключены" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "Не указан email. Пожалуйста, обновите ваш email." + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "" +"Your user is in an external Source of Record; some details cannot be " +"managed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "Отображать закрытые pull-request'ы" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "Открыто мной" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "Pull-request #%s открыт %s" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "Закрыто" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "Подтвердите удаление этого pull-request'а" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "Здесь ничего нет" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "Моё участие" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "Pull-request #%s открыт пользователем %s %s" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "Репозитории, где вы - владелец" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "Записи не найдены." + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "Репозитории, за которыми вы наблюдаете" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 msgid "My Notifications" msgstr "Мои уведомления" -#: rhodecode/templates/admin/notifications/notifications.html:29 +#: kallithea/templates/admin/notifications/notifications.html:32 msgid "All" msgstr "Всё" -#: rhodecode/templates/admin/notifications/notifications.html:30 +#: kallithea/templates/admin/notifications/notifications.html:33 msgid "Comments" msgstr "Комментарии" -#: rhodecode/templates/admin/notifications/notifications.html:31 -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:8 -msgid "Pull requests" -msgstr "Запросы pull" - -#: rhodecode/templates/admin/notifications/notifications.html:35 +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" +msgstr "Pull-request'ы" + +#: kallithea/templates/admin/notifications/notifications.html:38 msgid "Mark all read" msgstr "Пометить прочтённым" -#: rhodecode/templates/admin/notifications/notifications_data.html:39 +#: kallithea/templates/admin/notifications/notifications_data.html:40 msgid "No notifications here yet" msgstr "Уведомлений нет" -#: rhodecode/templates/admin/notifications/show_notification.html:5 -#: rhodecode/templates/admin/notifications/show_notification.html:11 +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 msgid "Show notification" msgstr "Показать уведомление" -#: rhodecode/templates/admin/notifications/show_notification.html:9 -#: rhodecode/templates/base/base.html:253 +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 msgid "Notifications" msgstr "Уведомления" -#: rhodecode/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:5 msgid "Permissions administration" msgstr "Управление привилегиями" -#: rhodecode/templates/admin/permissions/permissions.html:11 -#: rhodecode/templates/admin/repos/repo_edit.html:151 -#: rhodecode/templates/admin/repos/repo_edit.html:158 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:81 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:88 -#: rhodecode/templates/admin/users/user_edit.html:150 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:129 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:136 -#: rhodecode/templates/base/base.html:78 +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 msgid "Permissions" msgstr "Привилегии" -#: rhodecode/templates/admin/permissions/permissions.html:24 -msgid "Default permissions" -msgstr "Стандартные привилегии" - -#: rhodecode/templates/admin/permissions/permissions.html:31 +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "Белый список IP" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "Обзор" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 msgid "Anonymous access" msgstr "Анонимный доступ" -#: rhodecode/templates/admin/permissions/permissions.html:49 +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without need to log in. Anonymous users use %s " +"user permissions" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 msgid "" "All default permissions on each repository will be reset to chosen " -"permission, note that all custom default permission on repositories will be " -"lost" -msgstr "Выбранные значения прав будут установлены как значения по умолчанию для каждого репозитория. Учтите, что ранее установленные значения прав по умолчанию для репозиториев будут сброшены." - -#: rhodecode/templates/admin/permissions/permissions.html:50 -#: rhodecode/templates/admin/permissions/permissions.html:63 -#: rhodecode/templates/admin/permissions/permissions.html:77 +"permission, note that all custom default permission on repositories will " +"be lost" +msgstr "" +"Выбранные привилегии будут установлены по умолчанию для каждого " +"репозитория. Учтите, что ранее установленные привилегии по умолчанию " +"будут сброшены." + +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 msgid "Overwrite existing settings" msgstr "Перезаписать существующие настройки" -#: rhodecode/templates/admin/permissions/permissions.html:62 +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "Группа репозиториев" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 msgid "" "All default permissions on each repository group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" -msgstr "Выбранные значения прав будут установлены как значения по умолчанию для каждой группы репозиториев. Учтите, что ранее установленные значения прав по умолчанию для групп репозиториев будут сброшены." - -#: rhodecode/templates/admin/permissions/permissions.html:69 +msgstr "" +"Выбранные привилегии будут установлены по умолчанию для каждой группы " +"репозиториев. Учтите, что ранее установленные привилегии по умолчанию для" +" групп репозиториев будут сброшены." + +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 msgid "User group" msgstr "Группа пользователей" -#: rhodecode/templates/admin/permissions/permissions.html:76 +#: kallithea/templates/admin/permissions/permissions_globals.html:53 msgid "" "All default permissions on each user group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" -msgstr "Выбранные значения прав будут установлены как значения по умолчанию для каждой группы пользователей. Учтите, что ранее установленные значения прав по умолчанию для групп пользователей будут сброшены." - -#: rhodecode/templates/admin/permissions/permissions.html:83 +msgstr "" +"Выбранные привилегии будут установлены по умолчанию для каждой группы " +"пользователей. Учтите, что ранее установленные привилегии по умолчанию " +"для групп пользователей будут сброшены." + +#: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" msgstr "Создание репозитория" -#: rhodecode/templates/admin/permissions/permissions.html:91 +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "" +"Write permission to repository groups allows creating repositories inside" +" that group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 msgid "User group creation" msgstr "Создание групп пользователей" -#: rhodecode/templates/admin/permissions/permissions.html:99 +#: kallithea/templates/admin/permissions/permissions_globals.html:85 msgid "Repository forking" msgstr "Создание форка репозитория" -#: rhodecode/templates/admin/permissions/permissions.html:107 +#: kallithea/templates/admin/permissions/permissions_globals.html:93 msgid "Registration" msgstr "Регистрация" -#: rhodecode/templates/admin/permissions/permissions.html:115 +#: kallithea/templates/admin/permissions/permissions_globals.html:101 msgid "External auth account activation" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:133 -msgid "Default User Permissions" -msgstr "Права по умолчанию" - -#: rhodecode/templates/admin/permissions/permissions.html:144 -#: rhodecode/templates/admin/users/user_edit.html:207 -msgid "Allowed IP addresses" -msgstr "Разрешенные IP-адреса" - -#: rhodecode/templates/admin/permissions/permissions.html:158 -#: rhodecode/templates/admin/repos/repo_edit.html:340 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#: rhodecode/templates/admin/users/user_edit.html:175 -#: rhodecode/templates/admin/users/user_edit.html:220 -#: rhodecode/templates/admin/users_groups/users_groups.html:54 -#: rhodecode/templates/data_table/_dt_elements.html:122 -#: rhodecode/templates/data_table/_dt_elements.html:136 -msgid "delete" -msgstr "удалить" - -#: rhodecode/templates/admin/permissions/permissions.html:159 -#: rhodecode/templates/admin/users/user_edit.html:221 +msgstr "Активация сторонней учетной записи" + +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "Белый список IP для всех пользователей" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 #, python-format msgid "Confirm to delete this ip: %s" msgstr "Подтвердите удаление ip %s" -#: rhodecode/templates/admin/permissions/permissions.html:165 -#: rhodecode/templates/admin/users/user_edit.html:227 +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 msgid "All IP addresses are allowed" msgstr "Разрешены любые IP-адреса" -#: rhodecode/templates/admin/permissions/permissions.html:176 -#: rhodecode/templates/admin/users/user_edit.html:238 +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" msgstr "Новый ip-адрес" -#: rhodecode/templates/admin/permissions/permissions.html:184 -#: rhodecode/templates/admin/repos/repo_add_base.html:73 -#: rhodecode/templates/admin/repos/repo_edit.html:380 -#: rhodecode/templates/admin/users/user_edit.html:197 -#: rhodecode/templates/admin/users/user_edit.html:245 -msgid "Add" -msgstr "Добавить" - -#: rhodecode/templates/admin/repos/repo_add.html:12 -#: rhodecode/templates/admin/repos/repo_add.html:16 -#: rhodecode/templates/base/base.html:74 rhodecode/templates/base/base.html:88 -#: rhodecode/templates/base/base.html:116 -#: rhodecode/templates/base/base.html:275 -msgid "Repositories" -msgstr "Репозитории" - -#: rhodecode/templates/admin/repos/repo_add.html:19 -msgid "Add new" -msgstr "Добавить новый" - -#: rhodecode/templates/admin/repos/repo_add_base.html:20 -#: rhodecode/templates/summary/summary.html:96 -#: rhodecode/templates/summary/summary.html:97 -msgid "Clone from" -msgstr "Клонировать из" - -#: rhodecode/templates/admin/repos/repo_add_base.html:24 -#: rhodecode/templates/admin/repos/repo_edit.html:45 -msgid "Optional http[s] url from which repository should be cloned." -msgstr "Опциональный url http[s], с которого требуется склонировать репозиторий." - -#: rhodecode/templates/admin/repos/repo_add_base.html:33 -#: rhodecode/templates/forks/fork.html:51 -msgid "Optionaly select a group to put this repository into." -msgstr "Опционально выбрать группу, в которую поместить данный репозиторий." - -#: rhodecode/templates/admin/repos/repo_add_base.html:42 -msgid "Type of repository to create." -msgstr "Тип создаваемого репозитория." - -#: rhodecode/templates/admin/repos/repo_add_base.html:47 -#: rhodecode/templates/admin/repos/repo_edit.html:59 -#: rhodecode/templates/forks/fork.html:38 -msgid "Landing revision" -msgstr "Ревизия для выгрузки" - -#: rhodecode/templates/admin/repos/repo_add_base.html:51 -#: rhodecode/templates/admin/repos/repo_edit.html:63 -#: rhodecode/templates/forks/fork.html:42 -msgid "Default revision for files page, downloads, whoosh and readme" -msgstr "Ревизия по умолчанию, из которой будет производиться выгрузка файлов при скачивании" - -#: rhodecode/templates/admin/repos/repo_add_base.html:60 -#: rhodecode/templates/admin/repos/repo_edit.html:72 -#: rhodecode/templates/forks/fork.html:60 -msgid "" -"Keep it short and to the point. Use a README file for longer descriptions." -msgstr "Короткое и осмысленное. Для развернутого описания используйте файл README." - -#: rhodecode/templates/admin/repos/repo_edit.html:8 -msgid "Edit repository" -msgstr "Редактировать репозиторий" - -#: rhodecode/templates/admin/repos/repo_edit.html:12 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:11 -#: rhodecode/templates/base/base.html:81 -#: rhodecode/templates/base/base.html:134 -#: rhodecode/templates/summary/summary.html:212 +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "Обзор прав пользователей по-умолчанию" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "Добавить группу репозиториев" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "Группы репозиториев" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "Имя группы" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "Родительская группа" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "Группы репозиториев" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "Добавить подгруппу" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 msgid "Settings" msgstr "Настройки" -#: rhodecode/templates/admin/repos/repo_edit.html:36 -msgid "Non-changeable id" -msgstr "Неизменяемый id" - -#: rhodecode/templates/admin/repos/repo_edit.html:41 -msgid "Clone uri" -msgstr "URI для клонирования" - -#: rhodecode/templates/admin/repos/repo_edit.html:54 -msgid "Optional select a group to put this repository into." -msgstr "Опционально выбрать группу, в которую поместить данный репозиторий." - -#: rhodecode/templates/admin/repos/repo_edit.html:119 -msgid "Change owner of this repository." -msgstr "Изменить владельца репозитория" - -#: rhodecode/templates/admin/repos/repo_edit.html:177 -msgid "Advanced settings" -msgstr "Дополнительные настройки" - -#: rhodecode/templates/admin/repos/repo_edit.html:180 -msgid "Statistics" -msgstr "Статистика" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Reset current statistics" -msgstr "Сбросить статистику" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Confirm to remove current statistics" -msgstr "Подтвердите сброс статистики" - -#: rhodecode/templates/admin/repos/repo_edit.html:187 -msgid "Fetched to rev" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:188 -msgid "Stats gathered" -msgstr "Полученная статистика" - -#: rhodecode/templates/admin/repos/repo_edit.html:196 -msgid "Remote" -msgstr "Удалённый" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Pull changes from remote location" -msgstr "Получить изменения с удалённой стороны" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Confirm to pull changes from remote side" -msgstr "Подтвердите скачивание изменений" - -#: rhodecode/templates/admin/repos/repo_edit.html:211 -msgid "Cache" -msgstr "Кэш" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Invalidate repository cache" -msgstr "Сбросить кэш репозитория" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Confirm to invalidate repository cache" -msgstr "Подтвердите сброс кэша" - -#: rhodecode/templates/admin/repos/repo_edit.html:218 -msgid "" -"Manually invalidate cache for this repository. On first access repository " -"will be cached again" -msgstr "Ручной сброс кэша репозитория. При первом доступе кэш восстановится." - -#: rhodecode/templates/admin/repos/repo_edit.html:223 -msgid "List of cached values" -msgstr "Список кешированных значений" - -#: rhodecode/templates/admin/repos/repo_edit.html:226 -msgid "Prefix" -msgstr "Префикс" - -#: rhodecode/templates/admin/repos/repo_edit.html:227 -msgid "Key" -msgstr "Ключ" - -#: rhodecode/templates/admin/repos/repo_edit.html:228 -#: rhodecode/templates/admin/users/user_add.html:86 -#: rhodecode/templates/admin/users/user_edit.html:124 -#: rhodecode/templates/admin/users/users.html:84 -#: rhodecode/templates/admin/users_groups/users_group_add.html:41 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 -#: rhodecode/templates/admin/users_groups/users_groups.html:39 -msgid "Active" -msgstr "Активный" - -#: rhodecode/templates/admin/repos/repo_edit.html:243 -#: rhodecode/templates/base/base.html:292 -#: rhodecode/templates/base/base.html:293 -msgid "Public journal" -msgstr "Общедоступный журнал" - -#: rhodecode/templates/admin/repos/repo_edit.html:249 -msgid "Remove from public journal" -msgstr "Удалить из общедоступного журнала" - -#: rhodecode/templates/admin/repos/repo_edit.html:251 -msgid "Add to public journal" -msgstr "Добавить в общедоступный журнал" - -#: rhodecode/templates/admin/repos/repo_edit.html:256 -msgid "" -"All actions made on this repository will be accessible to everyone in public" -" journal" -msgstr "Все производимые с этим репозиторием действия будут доступны для всех из общедоступного журнала" - -#: rhodecode/templates/admin/repos/repo_edit.html:263 -msgid "Locking" -msgstr "Блокировка" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Unlock locked repo" -msgstr "Разблокировать репозиторий" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Confirm to unlock repository" -msgstr "Подтвердите снятие блокировки с репозитория" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Lock repo" -msgstr "Заблокировать репозиторий" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Confirm to lock repository" -msgstr "Подтвердите блокировку репозитория" - -#: rhodecode/templates/admin/repos/repo_edit.html:272 -msgid "Repository is not locked" -msgstr "Репозиторий не заблокирован" - -#: rhodecode/templates/admin/repos/repo_edit.html:277 -msgid "" -"Force locking on repository. Works only when anonymous access is disabled" -msgstr "Принудительная блокировка репозитория. Работает только при отключенном доступе для неавторизованных." - -#: rhodecode/templates/admin/repos/repo_edit.html:284 -msgid "Set as fork of" -msgstr "Сделать форком от" - -#: rhodecode/templates/admin/repos/repo_edit.html:289 -msgid "Set" -msgstr "Набор" - -#: rhodecode/templates/admin/repos/repo_edit.html:293 -msgid "Manually set this repository as a fork of another from the list" -msgstr "Вручную сделать этот репозиторий форком выбранного из списка" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Remove this repository" -msgstr "Удалить репозиторий" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Confirm to delete this repository" -msgstr "Подтвердите удаление репозитория" - -#: rhodecode/templates/admin/repos/repo_edit.html:310 -#, python-format -msgid "this repository has %s fork" -msgid_plural "this repository has %s forks" -msgstr[0] "данный репозиторий имеет %s копию" -msgstr[1] "данный репозиторий имеет %s копии" -msgstr[2] "данный репозиторий имеет %s копий" - -#: rhodecode/templates/admin/repos/repo_edit.html:311 -msgid "Detach forks" -msgstr "Отсоединить fork'и" - -#: rhodecode/templates/admin/repos/repo_edit.html:312 -msgid "Delete forks" -msgstr "Удалить fork'и" - -#: rhodecode/templates/admin/repos/repo_edit.html:315 -msgid "" -"This repository will be renamed in a special way in order to be unaccesible " -"for RhodeCode and VCS systems. If you need to fully delete it from file " -"system please do it manually" -msgstr "Этот репозитарий будет переименован таким образом, чтобы сделать его недоступным для RhodeCode и систем управления версиями. Если вам необходимо полностью удалить его из файловой системы, пожалуйста, сделайте это вручную" - -#: rhodecode/templates/admin/repos/repo_edit.html:329 -msgid "Extra fields" -msgstr "Дополнительные поля" - -#: rhodecode/templates/admin/repos/repo_edit.html:341 -#, python-format -msgid "Confirm to delete this field: %s" -msgstr "Подтвердите удаление этого поля: %s" - -#: rhodecode/templates/admin/repos/repo_edit.html:355 -msgid "New field key" -msgstr "Ключ" - -#: rhodecode/templates/admin/repos/repo_edit.html:363 -msgid "New field label" -msgstr "Имя поля" - -#: rhodecode/templates/admin/repos/repo_edit.html:366 -msgid "Enter short label" -msgstr "Введите краткое имя поля" - -#: rhodecode/templates/admin/repos/repo_edit.html:372 -msgid "New field description" -msgstr "Описание поля" - -#: rhodecode/templates/admin/repos/repo_edit.html:375 -msgid "Enter description of a field" -msgstr "Введите описание поля" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:3 -msgid "none" -msgstr "ничего" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:4 -msgid "read" -msgstr "читать" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:5 -msgid "write" -msgstr "записывать" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:6 -msgid "admin" -msgstr "администратор" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:7 -msgid "member" -msgstr "участник" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:16 -msgid "private repository" -msgstr "приватный репозиторий" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:19 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:28 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:20 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:35 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:20 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:35 -msgid "default" -msgstr "по-умолчанию" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:33 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:58 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:25 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:55 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:25 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:55 -msgid "revoke" -msgstr "отозвать" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:83 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:81 -msgid "Add another member" -msgstr "Добавить другого участника" - -#: rhodecode/templates/admin/repos/repos.html:5 -msgid "Repositories administration" -msgstr "Администрирование репозиториев" - -#: rhodecode/templates/admin/repos/repos.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account.html:185 -#: rhodecode/templates/admin/users/users.html:109 -#: rhodecode/templates/bookmarks/bookmarks.html:76 -#: rhodecode/templates/branches/branches.html:75 -#: rhodecode/templates/journal/journal.html:206 -#: rhodecode/templates/journal/journal.html:296 -#: rhodecode/templates/tags/tags.html:76 -msgid "No records found." -msgstr "Записи не найдены." - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:87 -msgid "apply to children" -msgstr "применить к дочерним" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:88 -msgid "" -"Set or revoke permission to all children of that group, including non-" -"private repositories and other groups" -msgstr "Назначить или отозвать привилегии всем в группе, включая общедоступные репозитории и другие группы." - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:4 -#, python-format -msgid "%s Group Dashboard" -msgstr "Панель группы %s" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:9 -msgid "Home" -msgstr "Домой" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:13 -msgid "with" -msgstr "с" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5 -msgid "Add repository group" -msgstr "Добавить группу репозиториев" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:16 -#: rhodecode/templates/base/base.html:75 rhodecode/templates/base/base.html:91 -msgid "Repository groups" -msgstr "Группы репозиториев" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:13 -msgid "Add new repository group" -msgstr "Добавить новую группу репозиториев" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:51 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:56 -msgid "Group parent" -msgstr "Родительская группа" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:59 -msgid "save" -msgstr "сохранить" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5 -msgid "Edit repository group" -msgstr "Редактировать группу репозиториев" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:13 -#, python-format -msgid "Edit repository group %s" -msgstr "Редактировать группу репозиториев %s" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:27 -msgid "Add child group" -msgstr "Добавить дочернюю группу" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:68 -msgid "" -"Enable lock-by-pulling on group. This option will be applied to all other " -"groups and repositories inside" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5 -msgid "Repository groups administration" -msgstr "Администрирование групп репозиториев" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:45 -msgid "Number of toplevel repositories" -msgstr "Число репозиториев верхнего уровня" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:64 -#: rhodecode/templates/admin/users_groups/users_groups.html:48 -#: rhodecode/templates/changeset/changeset_file_comment.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:171 -msgid "Edit" -msgstr "Редактировать" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:65 -#: rhodecode/templates/admin/users_groups/users_groups.html:49 -#: rhodecode/templates/base/perms_summary.html:29 -#: rhodecode/templates/base/perms_summary.html:60 -#: rhodecode/templates/base/perms_summary.html:62 -#: rhodecode/templates/data_table/_dt_elements.html:116 -#: rhodecode/templates/data_table/_dt_elements.html:117 -#: rhodecode/templates/data_table/_dt_elements.html:130 -#: rhodecode/templates/data_table/_dt_elements.html:131 -msgid "edit" -msgstr "редактировать" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" +msgstr "Дополнительно" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "Группа репозиториев: %s" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "Создано" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 #, python-format msgid "Confirm to delete this group: %s with %s repository" msgid_plural "Confirm to delete this group: %s with %s repositories" @@ -2828,968 +3155,1640 @@ msgstr[0] "Подтвердите удаление группы %s содержащей %s репозиториев." msgstr[1] "Подтвердите удаление группы %s содержащей %s репозиториев." msgstr[2] "Подтвердите удаление группы %s содержащей %s репозиториев." -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:78 -msgid "There are no repository groups yet" -msgstr "Группы репозиториев еще не созданы" - -#: rhodecode/templates/admin/settings/hooks.html:5 -#: rhodecode/templates/admin/settings/settings.html:5 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "ничего" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "читать" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "записывать" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "администратор" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "по-умолчанию" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "отозвать" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "Добавить новый" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "применить к дочерним" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "" +"Set or revoke permission to all children of that group, including non-" +"private repositories and other groups if selected." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "" +"Enable lock-by-pulling on group. This option will be applied to all other" +" groups and repositories inside" +msgstr "" +"Включить lock-by-pulling для группы. Эта опция будет применена ко всем " +"дочерним группам и репозиториям" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "%s Repository group dashboard" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "Домой" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "с" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "Администрирование групп репозиториев" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "Число репозиториев верхнего уровня" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "Добавить репозиторий" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "Клонировать из" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "Опциональный url http[s], с которого требуется склонировать репозиторий." + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "Короткое и осмысленное. Для развернутого описания используйте файл README." + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "Опционально выбрать группу, в которую поместить данный репозиторий." + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "Тип создаваемого репозитория." + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "Ревизия для выгрузки" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is beeing created, you will be redirected " +"when this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:42 +msgid "" +"We're sorry but error occured during this operation. Please check your " +"Kallithea server logs, or contact administrator." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, python-format +msgid "%s repository settings" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "Дополнительные поля" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +msgid "Remote" +msgstr "Удалённый" + +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "Статистика" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "Форк от" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "Набор" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "Вручную сделать этот репозиторий форком выбранного из списка" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Remove from public journal" +msgstr "Удалить из общедоступного журнала" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +msgid "Add to public journal" +msgstr "Добавить в общедоступный журнал" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 +msgid "" +"All actions made on this repository will be accessible to everyone in " +"public journal" +msgstr "" +"Все производимые с этим репозиторием действия будут отображаться в " +"общедостпном журнале " + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 +msgid "Confirm to unlock repository" +msgstr "Подтвердите снятие блокировки с репозитория" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 +msgid "Confirm to lock repository" +msgstr "Подтвердите блокировку репозитория" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 +msgid "Repository is not locked" +msgstr "Репозиторий не заблокирован" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 +msgid "" +"Force locking on repository. Works only when anonymous access is " +"disabled. Trigering a pull locks repository by user who pulled, only the " +"same user can unlock by doing a push" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "Подтвердите удаление этого репозитория: %s" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +msgid "Delete this repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 +#, python-format +msgid "this repository has %s fork" +msgid_plural "this repository has %s forks" +msgstr[0] "данный репозиторий имеет %s копию" +msgstr[1] "данный репозиторий имеет %s копии" +msgstr[2] "данный репозиторий имеет %s копий" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 +msgid "Detach forks" +msgstr "Отсоединить fork'и" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 +msgid "Delete forks" +msgstr "Удалить fork'и" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "" +"This repository will be renamed in a special way in order to be " +"unaccesible for Kallithea and VCS systems. If you need to fully delete it" +" from file system please do it manually" +msgstr "" +"Этот репозитарий будет переименован таким образом, чтобы сделать его " +"недоступным для Kallithea и систем управления версиями. Если вам " +"необходимо полностью удалить его из файловой системы, пожалуйста, " +"сделайте это вручную" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "Сбросить кэш репозитория" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "Подтвердите сброс кэша" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 +msgid "" +"Manually invalidate cache for this repository. On first access repository" +" will be cached again" +msgstr "Ручной сброс кэша репозитория. При первом доступе кэш восстановится." + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "Список кешированных значений" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "Префикс" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "Ключ" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "Активный" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#, python-format +msgid "Confirm to delete this field: %s" +msgstr "Подтвердите удаление этого поля: %s" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 +msgid "New field key" +msgstr "Ключ" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 +msgid "New field label" +msgstr "Имя поля" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 +msgid "Enter short label" +msgstr "Введите краткое имя поля" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 +msgid "New field description" +msgstr "Описание поля" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +msgid "Enter description of a field" +msgstr "Введите описание поля" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 +msgid "private repository" +msgstr "приватный репозиторий" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "Получить изменения с удалённой стороны" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "Подтвердите скачивание изменений" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "Неизменяемый id" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 +msgid "" +"In case this repository is renamed or moved into another group the " +"repository url changes.\n" +" Using above url guarantees that this " +"repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases" +" that you need to hardcode the url into 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "URI для клонирования" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "редактировать" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "Опционально выбрать группу, в которую поместить данный репозиторий." + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "" +"Ревизия по умолчанию, из которой будет производиться выгрузка файлов при " +"скачивании" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "Изменить владельца репозитория" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "Подтвердите сброс статистики" + +#: kallithea/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "Администрирование репозиториев" + +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 msgid "Settings administration" msgstr "Администрирование настроек" -#: rhodecode/templates/admin/settings/hooks.html:24 -msgid "Built in hooks - read only" -msgstr "Встроенные хуки - только для чтения" - -#: rhodecode/templates/admin/settings/hooks.html:40 -msgid "Custom hooks" -msgstr "Пользовательские хуки" - -#: rhodecode/templates/admin/settings/hooks.html:56 -msgid "remove" -msgstr "удалить" - -#: rhodecode/templates/admin/settings/hooks.html:88 -msgid "Failed to remove hook" -msgstr "Не удалось удалить хук" - -#: rhodecode/templates/admin/settings/settings.html:26 -msgid "Remap and rescan repositories" -msgstr "Переназначение и повторное сканирование" - -#: rhodecode/templates/admin/settings/settings.html:34 -msgid "Rescan option" -msgstr "Опции пересканирования" - -#: rhodecode/templates/admin/settings/settings.html:40 -msgid "" -"In case a repository was deleted from filesystem and there are leftovers in " -"the database check this option to scan obsolete data in database and remove " -"it." -msgstr "В случае, если репозитарий был удален из файловой системы, и в базе данных осталась информация относящаяся к нему, эта опция найдёт устаревшие данные в базе и удалит их." - -#: rhodecode/templates/admin/settings/settings.html:41 -msgid "Destroy old data" -msgstr "Уничтожить все данные" - -#: rhodecode/templates/admin/settings/settings.html:43 -msgid "" -"Rescan repositories location for new repositories. Also deletes obsolete if " -"`destroy` flag is checked " -msgstr "Обновить месторасположение хранилищ. Также удалить устаревшие хранилища если флаг \"уничтожить все данные\" установлен." - -#: rhodecode/templates/admin/settings/settings.html:48 -msgid "Rescan repositories" -msgstr "Пересканировать репозитории" - -#: rhodecode/templates/admin/settings/settings.html:54 -msgid "Whoosh indexing" -msgstr "Индексация Whoosh" - -#: rhodecode/templates/admin/settings/settings.html:62 -msgid "Index build option" -msgstr "Опции создания индекса" - -#: rhodecode/templates/admin/settings/settings.html:67 -msgid "Build from scratch" -msgstr "Сборка с нуля" - -#: rhodecode/templates/admin/settings/settings.html:73 -msgid "Reindex" -msgstr "Перестроить индекс" - -#: rhodecode/templates/admin/settings/settings.html:79 -msgid "Global application settings" -msgstr "Глобальные настройки" - -#: rhodecode/templates/admin/settings/settings.html:88 +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "Хуки" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:16 +msgid "SMTP auth" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:39 +msgid "Send" +msgstr "Отправить" + +#: kallithea/templates/admin/settings/settings_global.html:8 msgid "Site branding" msgstr "Брендинг сайта" -#: rhodecode/templates/admin/settings/settings.html:97 +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:18 msgid "HTTP authentication realm" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:106 +msgstr "Приветствие для HTTP-аутентификации" + +#: kallithea/templates/admin/settings/settings_global.html:27 msgid "Google Analytics code" msgstr "Код Google Analytics" -#: rhodecode/templates/admin/settings/settings.html:114 -#: rhodecode/templates/admin/settings/settings.html:195 -#: rhodecode/templates/admin/settings/settings.html:287 +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:50 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 msgid "Save settings" msgstr "Сохранить настройки" -#: rhodecode/templates/admin/settings/settings.html:121 -msgid "Visualisation settings" -msgstr "Настройки визуализации" - -#: rhodecode/templates/admin/settings/settings.html:129 -msgid "General" -msgstr "Главное" - -#: rhodecode/templates/admin/settings/settings.html:134 -msgid "Use repository extra fields" -msgstr "Использовать дополнительные поля в репозиториях" - -#: rhodecode/templates/admin/settings/settings.html:136 -msgid "Allows storing additional customized fields per repository." -msgstr "Позволяет хранить дополнительные поля в репозиториях" - -#: rhodecode/templates/admin/settings/settings.html:139 -msgid "Show RhodeCode version" -msgstr "Отображать версию RhodeCode" - -#: rhodecode/templates/admin/settings/settings.html:141 -msgid "Shows or hides displayed version of RhodeCode in the footer" -msgstr "Показать или скрыть версию RhodeCode в нижней части страницы" - -#: rhodecode/templates/admin/settings/settings.html:146 -msgid "Dashboard items" -msgstr "Элементы панели" - -#: rhodecode/templates/admin/settings/settings.html:150 +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "" +"Hooks can be used to trigger actions on certain events such as push / " +"pull. They can trigger Python functions or external applications." +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 +msgid "Custom hooks" +msgstr "Пользовательские хуки" + +#: kallithea/templates/admin/settings/settings_hooks.html:69 +msgid "Failed to remove hook" +msgstr "Не удалось удалить хук" + +#: kallithea/templates/admin/settings/settings_mapping.html:6 +msgid "Rescan option" +msgstr "Опции пересканирования" + +#: kallithea/templates/admin/settings/settings_mapping.html:11 +msgid "Destroy old data" +msgstr "Уничтожить все данные" + +#: kallithea/templates/admin/settings/settings_mapping.html:13 +msgid "" +"In case a repository was deleted from filesystem and it still exists in " +"the database check this option to scan obsolete data in database and " +"remove it." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "Сбросить кэш для всех репозиториев" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 +msgid "" +"Each cache data for repositories will be cleaned with this option " +"selected. Use this to reload data and clear cache keys." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 msgid "" -"Number of items displayed in lightweight dashboard before pagination is " -"shown." -msgstr "Число показываемых пунктов, показанных в облегчённой приборной панели перед нумерацией страниц." - -#: rhodecode/templates/admin/settings/settings.html:155 -msgid "Icons" -msgstr "Иконки" - -#: rhodecode/templates/admin/settings/settings.html:160 -msgid "Show public repo icon on repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:164 -msgid "Show private repo icon on repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:166 -msgid "Show public/private icons next to repositories names" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:172 -msgid "Meta-Tagging" -msgstr "Метатегирование" - -#: rhodecode/templates/admin/settings/settings.html:177 -msgid "Stylify recognised metatags:" -msgstr "Stylify распознал метатеги:" - -#: rhodecode/templates/admin/settings/settings.html:204 -msgid "VCS settings" -msgstr "Настройки VCS" - -#: rhodecode/templates/admin/settings/settings.html:213 +"Verify if Kallitheas GIT hooks are installed for each repository. Current" +" hooks will be updated to latest version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:7 +msgid "Index build option" +msgstr "Опции создания индекса" + +#: kallithea/templates/admin/settings/settings_search.html:12 +msgid "Build from scratch" +msgstr "Сборка с нуля" + +#: kallithea/templates/admin/settings/settings_search.html:15 +msgid "" +"This option completely reindex all the files within Kallithea for proper " +"fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:21 +msgid "Reindex" +msgstr "Перестроить индекс" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 msgid "Web" msgstr "Веб" -#: rhodecode/templates/admin/settings/settings.html:218 +#: kallithea/templates/admin/settings/settings_vcs.html:11 msgid "Require SSL for vcs operations" msgstr "Запрашивать SSL для операций с VCS" -#: rhodecode/templates/admin/settings/settings.html:220 +#: kallithea/templates/admin/settings/settings_vcs.html:13 msgid "" -"RhodeCode will require SSL for pushing or pulling. If SSL is missing it will" -" return HTTP Error 406: Not Acceptable" -msgstr "RhodeCode будет запрашивать SSL для таких действий как push или pull. Если SSL не будет получен, то будет возвращена ошибка HTTP Error 406: Not Acceptable" - -#: rhodecode/templates/admin/settings/settings.html:226 -msgid "Hooks" -msgstr "Хуки" - -#: rhodecode/templates/admin/settings/settings.html:231 -msgid "Update repository after push (hg update)" -msgstr "Обновлять репозиторий после отправки (hg update)" - -#: rhodecode/templates/admin/settings/settings.html:235 +"Activate to set Kallithea to require SSL for pushing or pulling. If SSL " +"certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 msgid "Show repository size after push" msgstr "Показывать размер репозитория после отправки" -#: rhodecode/templates/admin/settings/settings.html:239 +#: kallithea/templates/admin/settings/settings_vcs.html:28 msgid "Log user push commands" msgstr "Логировать пользовательские команды отправки" -#: rhodecode/templates/admin/settings/settings.html:243 +#: kallithea/templates/admin/settings/settings_vcs.html:32 msgid "Log user pull commands" msgstr "Логировать пользовательские команды получения" -#: rhodecode/templates/admin/settings/settings.html:247 -msgid "Advanced setup" -msgstr "Расширенные настройки" - -#: rhodecode/templates/admin/settings/settings.html:252 +#: kallithea/templates/admin/settings/settings_vcs.html:36 +msgid "Update repository after push (hg update)" +msgstr "Обновлять репозиторий после отправки (hg update)" + +#: kallithea/templates/admin/settings/settings_vcs.html:42 msgid "Mercurial Extensions" msgstr "Расширения Mercurial" -#: rhodecode/templates/admin/settings/settings.html:257 +#: kallithea/templates/admin/settings/settings_vcs.html:47 msgid "Enable largefiles extension" msgstr "Включить поддержку больших файлов" -#: rhodecode/templates/admin/settings/settings.html:261 +#: kallithea/templates/admin/settings/settings_vcs.html:51 msgid "Enable hgsubversion extension" msgstr "Включить поддержку hgsubversion" -#: rhodecode/templates/admin/settings/settings.html:263 +#: kallithea/templates/admin/settings/settings_vcs.html:53 msgid "" -"Requires hgsubversion library installed. Allows cloning from svn remote " -"locations" -msgstr "Необходимые библиотеки hgsubversion установлены. Разрешено клонировать из svn репозиториев." - -#: rhodecode/templates/admin/settings/settings.html:274 +"Requires hgsubversion library to be installed. Allows cloning remote SVN " +"repositories and migrates them to Mercurial type." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 msgid "Repositories location" msgstr "Расположение репозитариев" -#: rhodecode/templates/admin/settings/settings.html:279 +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting" +" take effect." +msgstr "" +"Нажмите для разблокирования. Изменения вступят в силу после перезагрузки " +"Kallithea." + +#: kallithea/templates/admin/settings/settings_vcs.html:72 msgid "" -"Click to unlock. You must restart RhodeCode in order to make this setting " -"take effect." -msgstr "Нажмите для разблокирования. Изменения вступят в силу после перезагрузки RhodeCode." - -#: rhodecode/templates/admin/settings/settings.html:280 -#: rhodecode/templates/base/base.html:143 -msgid "Unlock" -msgstr "Разблокировать" - -#: rhodecode/templates/admin/settings/settings.html:282 +"Filesystem location where repositories should be stored. After changing " +"this value a restart and rescan of the repository folder are required." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:8 +msgid "General" +msgstr "Главное" + +#: kallithea/templates/admin/settings/settings_visual.html:13 +msgid "Use repository extra fields" +msgstr "Использовать дополнительные поля в репозиториях" + +#: kallithea/templates/admin/settings/settings_visual.html:15 +msgid "Allows storing additional customized fields per repository." +msgstr "Позволяет хранить дополнительные поля в репозиториях" + +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "Отображать версию Kallithea" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:30 +msgid "" +"Gravatar url allows you to use other avatar server application.\n" +" Following " +"variables of the URL will be replaced accordingly.\n" +" {scheme} " +"'http' or 'https' sent from running Kallithea server,\n" +" {email} user " +"email,\n" +" {md5email} md5 " +"hash of the user email (like at gravatar.com),\n" +" {size} size " +"of the image that is expected from the server application,\n" +" {netloc} " +"network location/server host of running Kallithea server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:42 msgid "" -"Location where repositories are stored. After changing this value a restart," -" and rescan is required" -msgstr "Расположение репозитариев сохранено. После изменения расположения необходимо перезагрузить и пересканировать" - -#: rhodecode/templates/admin/settings/settings.html:303 -msgid "Test Email" -msgstr "Тестовый E-mail" - -#: rhodecode/templates/admin/settings/settings.html:311 -msgid "Email to" -msgstr "Написать E-mail" - -#: rhodecode/templates/admin/settings/settings.html:319 -msgid "Send" -msgstr "Отправить" - -#: rhodecode/templates/admin/settings/settings.html:325 -msgid "System Info and Packages" -msgstr "Информация о системе и пакеты" - -#: rhodecode/templates/admin/settings/settings.html:328 -#: rhodecode/templates/changelog/changelog.html:51 -msgid "Show" -msgstr "Показать" - -#: rhodecode/templates/admin/users/user_add.html:5 -msgid "Add user" -msgstr "Добавить пользователя" - -#: rhodecode/templates/admin/users/user_add.html:10 -#: rhodecode/templates/admin/users/user_edit.html:11 -#: rhodecode/templates/base/base.html:76 -msgid "Users" -msgstr "Пользователи" - -#: rhodecode/templates/admin/users/user_add.html:12 -#: rhodecode/templates/admin/users/users.html:23 -msgid "Add new user" -msgstr "Добавить нового пользователя" - -#: rhodecode/templates/admin/users/user_add.html:50 -msgid "Password confirmation" -msgstr "Подтверждение пароля" - -#: rhodecode/templates/admin/users/user_edit.html:5 -msgid "Edit user" -msgstr "Редактировать пользователя" - -#: rhodecode/templates/admin/users/user_edit.html:13 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 -#, python-format -msgid "Edit %s" -msgstr "Редактировать %s" - -#: rhodecode/templates/admin/users/user_edit.html:34 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:10 -msgid "Change your avatar at" -msgstr "Измените аватарку через сайт" - -#: rhodecode/templates/admin/users/user_edit.html:35 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:11 -msgid "Using" -msgstr "Используется" - -#: rhodecode/templates/admin/users/user_edit.html:43 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:20 -msgid "API key" -msgstr "API ключ" - -#: rhodecode/templates/admin/users/user_edit.html:50 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:25 -msgid "Current IP" -msgstr "Текущий IP" - -#: rhodecode/templates/admin/users/user_edit.html:70 -msgid "LDAP DN" -msgstr "LDAP DN" - -#: rhodecode/templates/admin/users/user_edit.html:79 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:44 -msgid "New password" -msgstr "Новый пароль" - -#: rhodecode/templates/admin/users/user_edit.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:53 -msgid "New password confirmation" -msgstr "Подтвердите новый пароль" - -#: rhodecode/templates/admin/users/user_edit.html:163 -msgid "Email addresses" -msgstr "Адрес E-mail" - -#: rhodecode/templates/admin/users/user_edit.html:176 -#, python-format -msgid "Confirm to delete this email: %s" -msgstr "Подтвердите удаление E-mail: %s" - -#: rhodecode/templates/admin/users/user_edit.html:190 -msgid "New email address" -msgstr "Новый E-mail" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:5 -#: rhodecode/templates/base/base.html:254 -msgid "My account" -msgstr "Мой аккаунт" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:9 -msgid "My Account" -msgstr "Мой Аккаунт" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:35 -msgid "My permissions" -msgstr "Мои привилегии" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:38 -#: rhodecode/templates/journal/journal.html:54 -msgid "My repos" -msgstr "Мои репозитории" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:41 -msgid "My pull requests" -msgstr "Мои pull-request'ы" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:4 -msgid "Show closed pull requests" -msgstr "Отображать закрытые pull-request'ы" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:6 -msgid "Opened by me" -msgstr "Открыто мной" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "Pull-request #%s открыт %s" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:17 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:45 -#: rhodecode/templates/pullrequests/pullrequest_data.html:11 -#: rhodecode/templates/pullrequests/pullrequest_show.html:27 -#: rhodecode/templates/pullrequests/pullrequest_show.html:42 -msgid "Closed" -msgstr "Закрыто" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:23 -msgid "Confirm to delete this pull request" -msgstr "Подтвердите удаление этого pull-request'а" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:30 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:51 -msgid "Nothing here yet" -msgstr "Здесь ничего нет" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:34 -msgid "I participate in" -msgstr "Я участвую в" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:42 -#: rhodecode/templates/pullrequests/pullrequest_data.html:8 -#, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "Pull-request #%s открыт пользователем %s %s" - -#: rhodecode/templates/admin/users/users.html:5 -msgid "Users administration" -msgstr "Администрирование пользователей" - -#: rhodecode/templates/admin/users/users.html:9 -msgid "users" -msgstr "пользователи" - -#: rhodecode/templates/admin/users/users.html:80 -msgid "Firstname" -msgstr "Имя" - -#: rhodecode/templates/admin/users/users.html:81 -msgid "Lastname" -msgstr "Фамилия" - -#: rhodecode/templates/admin/users/users.html:82 -msgid "Last login" -msgstr "Последний вход" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:5 +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}'," +" available vars:\n" +" {scheme} 'http' " +"or 'https' sent from running Kallithea server,\n" +" {user} current " +"user username,\n" +" {netloc} network " +"location/server host of running Kallithea server,\n" +" {repo} full " +"repository name,\n" +" {repoid} ID of " +"repository, can be used to contruct clone-by-id" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:54 +msgid "Dashboard items" +msgstr "Элементы панели" + +#: kallithea/templates/admin/settings/settings_visual.html:58 +msgid "" +"Number of items displayed in the main page dashboard before pagination is" +" shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:68 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:74 +msgid "Icons" +msgstr "Иконки" + +#: kallithea/templates/admin/settings/settings_visual.html:79 +msgid "Show public repo icon on repositories" +msgstr "Показывать иконки публичных репозиториев" + +#: kallithea/templates/admin/settings/settings_visual.html:83 +msgid "Show private repo icon on repositories" +msgstr "Показывать иконки приватных репозиториев" + +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:91 +msgid "Meta-Tagging" +msgstr "Метатегирование" + +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:110 +msgid "" +"Parses meta tags from repository description field and turns them into " +"colored tags." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 msgid "Add user group" msgstr "Добавить группу пользователей" -#: rhodecode/templates/admin/users_groups/users_group_add.html:10 -#: rhodecode/templates/admin/users_groups/users_groups.html:11 -#: rhodecode/templates/base/base.html:77 rhodecode/templates/base/base.html:94 +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 msgid "User groups" msgstr "Группы пользователей" -#: rhodecode/templates/admin/users_groups/users_group_add.html:12 -#: rhodecode/templates/admin/users_groups/users_groups.html:26 -msgid "Add new user group" -msgstr "Добавить новую группу пользователей" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 -msgid "Edit user group" -msgstr "Редактировать группу пользователей" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 -msgid "UserGroups" -msgstr "Группы пользователей" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 -#: rhodecode/templates/admin/users_groups/users_groups.html:38 +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 +#, python-format +msgid "%s user group settings" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "Стандартные привилегии" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 msgid "Members" msgstr "Участники" -#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 -msgid "Chosen group members" -msgstr "Выбранные участники группы" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 -msgid "Remove all elements" -msgstr "Удалить всё" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 -msgid "Available members" -msgstr "Доступные участники" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 -msgid "Add all elements" -msgstr "Добавить всё" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:109 -msgid "No members yet" -msgstr "Нет участников" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:117 -msgid "Global Permissions" -msgstr "Глобальные права доступа" - -#: rhodecode/templates/admin/users_groups/users_groups.html:5 -msgid "User groups administration" -msgstr "Администрирование групп пользователей" - -#: rhodecode/templates/admin/users_groups/users_groups.html:55 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 +#, python-format +msgid "User Group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 #, python-format msgid "Confirm to delete this user group: %s" msgstr "Подтвердите удаление следующей группы пользователей: %s" -#: rhodecode/templates/admin/users_groups/users_groups.html:62 -msgid "There are no user groups yet" -msgstr "Группы пользователей еще не созданы" - -#: rhodecode/templates/base/base.html:42 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "Нет участников" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "Выбранные участники группы" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "Удалить всё" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "Доступные участники" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "Добавить всё" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "Администрирование групп пользователей" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 +msgid "Add user" +msgstr "Добавить пользователя" + +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 +msgid "Users" +msgstr "Пользователи" + +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:53 +msgid "Password confirmation" +msgstr "Подтверждение пароля" + +#: kallithea/templates/admin/users/user_edit.html:5 +#, python-format +msgid "%s user settings" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "Подтвердите удаление пользователя %s" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 +#, python-format +msgid "" +"This user is in an external Source of Record (%s); some details cannot be" +" managed here." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 +msgid "New password confirmation" +msgstr "Подтвердите новый пароль" + +#: kallithea/templates/admin/users/users.html:5 +msgid "Users administration" +msgstr "Администрирование пользователей" + +#: kallithea/templates/admin/users/users.html:13 +msgid "users" +msgstr "пользователи" + +#: kallithea/templates/admin/users/users.html:54 +msgid "Firstname" +msgstr "Имя" + +#: kallithea/templates/admin/users/users.html:55 +msgid "Lastname" +msgstr "Фамилия" + +#: kallithea/templates/admin/users/users.html:56 +msgid "Last login" +msgstr "Последний вход" + +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "" + +#: kallithea/templates/base/base.html:37 #, python-format msgid "Server instance: %s" msgstr "Экземпляр сервера: %s" -#: rhodecode/templates/base/base.html:52 -msgid "Report a bug" -msgstr "Сообщить об ошибке" - -#: rhodecode/templates/base/base.html:121 -#: rhodecode/templates/data_table/_dt_elements.html:9 -#: rhodecode/templates/data_table/_dt_elements.html:11 -#: rhodecode/templates/data_table/_dt_elements.html:13 -#: rhodecode/templates/summary/summary.html:8 +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 msgid "Summary" msgstr "Общие сведения" -#: rhodecode/templates/base/base.html:122 -#: rhodecode/templates/changelog/changelog.html:15 -#: rhodecode/templates/data_table/_dt_elements.html:17 -#: rhodecode/templates/data_table/_dt_elements.html:19 -#: rhodecode/templates/data_table/_dt_elements.html:21 +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 msgid "Changelog" msgstr "История изменений" -#: rhodecode/templates/base/base.html:123 -#: rhodecode/templates/data_table/_dt_elements.html:25 -#: rhodecode/templates/data_table/_dt_elements.html:27 -#: rhodecode/templates/data_table/_dt_elements.html:29 -#: rhodecode/templates/files/files.html:12 +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 msgid "Files" msgstr "Файлы" -#: rhodecode/templates/base/base.html:125 +#: kallithea/templates/base/base.html:149 msgid "Switch To" msgstr "Переключиться на" -#: rhodecode/templates/base/base.html:127 -#: rhodecode/templates/base/base.html:279 -msgid "loading..." -msgstr "Загрузка..." - -#: rhodecode/templates/base/base.html:131 +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 msgid "Options" msgstr "Опции" -#: rhodecode/templates/base/base.html:137 -#: rhodecode/templates/forks/forks_data.html:21 +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 msgid "Compare fork" msgstr "Сравнить форк" -#: rhodecode/templates/base/base.html:139 -#: rhodecode/templates/base/base.html:312 -#: rhodecode/templates/search/search.html:14 -#: rhodecode/templates/search/search.html:54 +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "Сравнить" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 msgid "Search" msgstr "Поиск" -#: rhodecode/templates/base/base.html:145 +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "Разблокировать" + +#: kallithea/templates/base/base.html:176 msgid "Lock" msgstr "Заблокировать" -#: rhodecode/templates/base/base.html:153 +#: kallithea/templates/base/base.html:184 msgid "Follow" msgstr "Наблюдать" -#: rhodecode/templates/base/base.html:154 +#: kallithea/templates/base/base.html:185 msgid "Unfollow" msgstr "Не наблюдать" -#: rhodecode/templates/base/base.html:157 -#: rhodecode/templates/data_table/_dt_elements.html:33 -#: rhodecode/templates/data_table/_dt_elements.html:35 -#: rhodecode/templates/data_table/_dt_elements.html:37 -#: rhodecode/templates/data_table/_dt_elements.html:74 -#: rhodecode/templates/forks/fork.html:9 +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 msgid "Fork" msgstr "Форк" -#: rhodecode/templates/base/base.html:159 +#: kallithea/templates/base/base.html:190 msgid "Create Pull Request" msgstr "Создать Pull запрос" -#: rhodecode/templates/base/base.html:165 -msgid "Show Pull Requests" -msgstr "Показать Pull запросы" - -#: rhodecode/templates/base/base.html:165 -msgid "Pull Requests" -msgstr "Pull-request'ы" - -#: rhodecode/templates/base/base.html:202 +#: kallithea/templates/base/base.html:196 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "Показать pull-request'ы для %s" + +#: kallithea/templates/base/base.html:233 msgid "Not logged in" msgstr "Не авторизован" -#: rhodecode/templates/base/base.html:209 +#: kallithea/templates/base/base.html:240 msgid "Login to your account" msgstr "Авторизоваться" -#: rhodecode/templates/base/base.html:232 +#: kallithea/templates/base/base.html:263 msgid "Forgot password ?" msgstr "Забыли пароль?" -#: rhodecode/templates/base/base.html:255 +#: kallithea/templates/base/base.html:286 msgid "Log Out" msgstr "Выход" -#: rhodecode/templates/base/base.html:274 -msgid "Switch repository" -msgstr "Переключить репозиторий" - -#: rhodecode/templates/base/base.html:286 +#: kallithea/templates/base/base.html:311 msgid "Show recent activity" msgstr "Показать последнюю активность" -#: rhodecode/templates/base/base.html:287 -#: rhodecode/templates/journal/journal.html:4 +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 msgid "Journal" msgstr "Журнал" -#: rhodecode/templates/base/base.html:298 +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "Общедоступный журнал" + +#: kallithea/templates/base/base.html:323 msgid "Show public gists" msgstr "Показать публичные записи" -#: rhodecode/templates/base/base.html:303 +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "Gist" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "Создать новую запись" + +#: kallithea/templates/base/base.html:328 msgid "All public gists" msgstr "Все публичные записи" -#: rhodecode/templates/base/base.html:305 +#: kallithea/templates/base/base.html:330 msgid "My public gists" msgstr "Мои публичные записи" -#: rhodecode/templates/base/base.html:306 +#: kallithea/templates/base/base.html:331 msgid "My private gists" msgstr "Мои приватные записи" -#: rhodecode/templates/base/base.html:311 +#: kallithea/templates/base/base.html:336 msgid "Search in repositories" -msgstr "Искать в репозитариях" - -#: rhodecode/templates/base/default_perms_box.html:14 -msgid "Inherit default permissions" -msgstr "Наследовать полномочия по умолчаинию" - -#: rhodecode/templates/base/default_perms_box.html:18 +msgstr "Поиск по репозиториям" + +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:19 #, python-format msgid "" -"Select to inherit permissions from %s settings. With this selected below " -"options does not apply." -msgstr "Выберите, чтобы унаследовать права из настроек %s. В этом случае опции ниже не будут применены." - -#: rhodecode/templates/base/default_perms_box.html:26 +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:28 msgid "Create repositories" msgstr "Создать репозитории" -#: rhodecode/templates/base/default_perms_box.html:30 +#: kallithea/templates/base/default_perms_box.html:33 msgid "Select this option to allow repository creation for this user" msgstr "Опция разрешает пользователю создавать репозитарии" -#: rhodecode/templates/base/default_perms_box.html:35 +#: kallithea/templates/base/default_perms_box.html:40 msgid "Create user groups" msgstr "Создавать группы пользователей" -#: rhodecode/templates/base/default_perms_box.html:39 +#: kallithea/templates/base/default_perms_box.html:45 msgid "Select this option to allow user group creation for this user" msgstr "Опция разрешает пользователю создавать группы пользователей" -#: rhodecode/templates/base/default_perms_box.html:44 +#: kallithea/templates/base/default_perms_box.html:52 msgid "Fork repositories" msgstr "Создавать fork от репозиториев" -#: rhodecode/templates/base/default_perms_box.html:48 +#: kallithea/templates/base/default_perms_box.html:57 msgid "Select this option to allow repository forking for this user" -msgstr "Выберите эту опцию чтобы разрешить данному пользователю создавать fork'и репозиториев" - -#: rhodecode/templates/base/perms_summary.html:11 +msgstr "" +"Выберите эту опцию чтобы разрешить данному пользователю создавать fork'и " +"репозиториев" + +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:22 msgid "No permissions defined yet" -msgstr "Права доступа еще не назначены" - -#: rhodecode/templates/base/perms_summary.html:19 -#: rhodecode/templates/base/perms_summary.html:38 +msgstr "Привилегии еще не назначены" + +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 msgid "Permission" msgstr "Привилегия" -#: rhodecode/templates/base/perms_summary.html:20 -#: rhodecode/templates/base/perms_summary.html:39 +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 msgid "Edit Permission" -msgstr "Изменить права доступа" - -#: rhodecode/templates/base/root.html:44 +msgstr "Изменить привилегии" + +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 msgid "Add another comment" msgstr "Добавить другой комментарий" -#: rhodecode/templates/base/root.html:45 -#: rhodecode/templates/data_table/_dt_elements.html:147 +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 msgid "Stop following this repository" msgstr "Отменить наблюдение за репозиторием" -#: rhodecode/templates/base/root.html:46 +#: kallithea/templates/base/root.html:47 msgid "Start following this repository" msgstr "Наблюдать за репозиторием" -#: rhodecode/templates/base/root.html:47 +#: kallithea/templates/base/root.html:48 msgid "Group" msgstr "Группа" -#: rhodecode/templates/base/root.html:48 +#: kallithea/templates/base/root.html:49 msgid "members" msgstr "участники" -#: rhodecode/templates/base/root.html:49 -#: rhodecode/templates/pullrequests/pullrequest.html:203 +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 msgid "Loading ..." msgstr "Загрузка..." -#: rhodecode/templates/base/root.html:50 +#: kallithea/templates/base/root.html:51 +msgid "loading ..." +msgstr "загрузка..." + +#: kallithea/templates/base/root.html:52 msgid "Search truncated" msgstr "Поиск усечен" -#: rhodecode/templates/base/root.html:51 +#: kallithea/templates/base/root.html:53 msgid "No matching files" msgstr "Нет совпадений" -#: rhodecode/templates/base/root.html:52 -#: rhodecode/templates/changelog/changelog.html:45 +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 msgid "Open new pull request" msgstr "Создать новый pull запрос" -#: rhodecode/templates/base/root.html:53 +#: kallithea/templates/base/root.html:55 msgid "Open new pull request for selected changesets" msgstr "Открыть новый pull-request для выделенных наборов изменений" -#: rhodecode/templates/base/root.html:54 +#: kallithea/templates/base/root.html:56 msgid "Show selected changesets __S -> __E" msgstr "Показать выбранные наборы изменений: __S -> __E" -#: rhodecode/templates/base/root.html:55 +#: kallithea/templates/base/root.html:57 msgid "Show selected changeset __S" msgstr "Показать выбранный набор изменений: __S" -#: rhodecode/templates/base/root.html:56 +#: kallithea/templates/base/root.html:58 msgid "Selection link" msgstr "Ссылка выбора" -#: rhodecode/templates/base/root.html:57 -#: rhodecode/templates/changeset/diff_block.html:8 +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 msgid "Collapse diff" msgstr "Свернуть сравнение" -#: rhodecode/templates/base/root.html:58 +#: kallithea/templates/base/root.html:60 msgid "Expand diff" msgstr "Раскрыть сравнение" -#: rhodecode/templates/base/root.html:59 +#: kallithea/templates/base/root.html:61 msgid "Failed to revoke permission" msgstr "Не удалось отозвать привилегии" -#: rhodecode/templates/bookmarks/bookmarks.html:5 +#: kallithea/templates/base/root.html:62 +msgid "confirm to revoke permission for {0}: {1} ?" +msgstr "подтвердите удаление привилегии для {0}: {1}" + +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:5 #, python-format msgid "%s Bookmarks" msgstr "Закладки %s" -#: rhodecode/templates/bookmarks/bookmarks.html:26 -msgid "Compare bookmarks" -msgstr "Сравнить закладки" - -#: rhodecode/templates/bookmarks/bookmarks.html:51 -#: rhodecode/templates/bookmarks/bookmarks_data.html:8 -#: rhodecode/templates/branches/branches.html:50 -#: rhodecode/templates/branches/branches_data.html:8 -#: rhodecode/templates/changelog/changelog_summary_data.html:8 -#: rhodecode/templates/tags/tags.html:51 -#: rhodecode/templates/tags/tags_data.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 msgid "Author" msgstr "Автор" -#: rhodecode/templates/bookmarks/bookmarks.html:52 -#: rhodecode/templates/bookmarks/bookmarks_data.html:9 -#: rhodecode/templates/branches/branches.html:51 -#: rhodecode/templates/branches/branches_data.html:9 -#: rhodecode/templates/changelog/changelog_summary_data.html:5 -#: rhodecode/templates/tags/tags.html:52 -#: rhodecode/templates/tags/tags_data.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 msgid "Revision" msgstr "Ревизия" -#: rhodecode/templates/bookmarks/bookmarks.html:54 -#: rhodecode/templates/bookmarks/bookmarks_data.html:10 -#: rhodecode/templates/branches/branches.html:53 -#: rhodecode/templates/branches/branches_data.html:10 -#: rhodecode/templates/tags/tags.html:54 -#: rhodecode/templates/tags/tags_data.html:10 -msgid "Compare" -msgstr "Сравнить" - -#: rhodecode/templates/branches/branches.html:5 +#: kallithea/templates/branches/branches.html:5 #, python-format msgid "%s Branches" msgstr "Ветки %s" -#: rhodecode/templates/branches/branches.html:26 -msgid "Compare branches" -msgstr "Сравнить ветки" - -#: rhodecode/templates/changelog/changelog.html:6 +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 #, python-format msgid "%s Changelog" msgstr "Логи изменений %s" -#: rhodecode/templates/changelog/changelog.html:19 +#: kallithea/templates/changelog/changelog.html:21 #, python-format msgid "showing %d out of %d revision" msgid_plural "showing %d out of %d revisions" -msgstr[0] "Показано %d из %d ревизий" -msgstr[1] "Показано %d из %d ревизий" +msgstr[0] "Показана %d из %d ревизий" +msgstr[1] "Показаны %d из %d ревизий" msgstr[2] "Показаны %d из %d ревизий " -#: rhodecode/templates/changelog/changelog.html:39 +#: kallithea/templates/changelog/changelog.html:43 msgid "Clear selection" msgstr "Очистить выбор" -#: rhodecode/templates/changelog/changelog.html:42 -#: rhodecode/templates/forks/forks_data.html:19 +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 #, python-format msgid "Compare fork with %s" msgstr "Сравнить fork с %s" -#: rhodecode/templates/changelog/changelog.html:42 -msgid "Compare fork with parent" -msgstr "Сравнить fork с родительским репозиторием" - -#: rhodecode/templates/changelog/changelog.html:78 -#: rhodecode/templates/changelog/changelog_summary_data.html:28 -#, python-format -msgid "Click to open associated pull request #%s" -msgstr "Нажмите для открытия ассоциированного запроса на внесение изменений #%s" - -#: rhodecode/templates/changelog/changelog.html:102 -#: rhodecode/templates/summary/summary.html:403 -msgid "Show more" -msgstr "Показать еще" - -#: rhodecode/templates/changelog/changelog.html:115 -#: rhodecode/templates/changelog/changelog_summary_data.html:50 -#: rhodecode/templates/changeset/changeset.html:107 -#: rhodecode/templates/changeset/changeset_range.html:86 +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "Показать" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 +#, python-format +msgid "" +"Changeset status: %s\n" +"Click to open associated pull request #%s" +msgstr "" +"Статус набора изенений: %s⏎\n" +"Кликрните, чтобы перейти к соответствующему pull-request'у #%s" + +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 +#, python-format +msgid "Changeset status: %s" +msgstr "Статус набора изменений: %s" + +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:114 +msgid "Changeset has comments" +msgstr "Комментарии отсутствуют" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 #, python-format msgid "Bookmark %s" msgstr "Закладка %s" -#: rhodecode/templates/changelog/changelog.html:121 -#: rhodecode/templates/changelog/changelog_summary_data.html:56 -#: rhodecode/templates/changeset/changeset.html:113 -#: rhodecode/templates/changeset/changeset_range.html:92 +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 #, python-format msgid "Tag %s" msgstr "Метка %s" -#: rhodecode/templates/changelog/changelog.html:126 -#: rhodecode/templates/changelog/changelog_summary_data.html:61 -#: rhodecode/templates/changeset/changeset.html:117 -#: rhodecode/templates/changeset/changeset_range.html:96 +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 #, python-format msgid "Branch %s" msgstr "Ветка %s" -#: rhodecode/templates/changelog/changelog.html:286 +#: kallithea/templates/changelog/changelog.html:299 msgid "There are no changes yet" msgstr "Изменений ещё нет" -#: rhodecode/templates/changelog/changelog_details.html:4 -#: rhodecode/templates/changeset/changeset.html:91 +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 msgid "Removed" msgstr "Удалено" -#: rhodecode/templates/changelog/changelog_details.html:5 -#: rhodecode/templates/changeset/changeset.html:92 +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 msgid "Changed" msgstr "Изменено" -#: rhodecode/templates/changelog/changelog_details.html:6 -#: rhodecode/templates/changeset/changeset.html:93 +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 msgid "Added" msgstr "Добавлено" -#: rhodecode/templates/changelog/changelog_details.html:8 -#: rhodecode/templates/changelog/changelog_details.html:9 -#: rhodecode/templates/changelog/changelog_details.html:10 -#: rhodecode/templates/changeset/changeset.html:95 -#: rhodecode/templates/changeset/changeset.html:96 -#: rhodecode/templates/changeset/changeset.html:97 +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 #, python-format msgid "Affected %s files" msgstr "Затрагивает %s файлов" -#: rhodecode/templates/changelog/changelog_summary_data.html:6 -#: rhodecode/templates/files/files_add.html:75 -#: rhodecode/templates/files/files_edit.html:61 +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 msgid "Commit message" msgstr "Сообщение commit'а" -#: rhodecode/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/changelog/changelog_summary_data.html:7 msgid "Age" msgstr "Возраст" -#: rhodecode/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/changelog/changelog_summary_data.html:9 msgid "Refs" msgstr "Ссылки" -#: rhodecode/templates/changelog/changelog_summary_data.html:86 -msgid "Add or upload files directly via RhodeCode" -msgstr "Добавить или загрузить файлы через RhodeCode" - -#: rhodecode/templates/changelog/changelog_summary_data.html:89 -#: rhodecode/templates/files/files_add.html:38 -#: rhodecode/templates/files/files_browser.html:31 -msgid "Add new file" -msgstr "Добавить файл" - -#: rhodecode/templates/changelog/changelog_summary_data.html:95 +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" +msgstr "Добавить или загрузить файлы через Kallithea" + +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:95 msgid "Push new repo" msgstr "Отправить новый репозиторий" -#: rhodecode/templates/changelog/changelog_summary_data.html:103 +#: kallithea/templates/changelog/changelog_summary_data.html:103 msgid "Existing repository?" msgstr "Существующий репозиторий?" -#: rhodecode/templates/changeset/changeset.html:6 +#: kallithea/templates/changeset/changeset.html:6 #, python-format msgid "%s Changeset" msgstr "%s Изменения" -#: rhodecode/templates/changeset/changeset.html:39 -msgid "No parents" -msgstr "Родители отсутвуют" - -#: rhodecode/templates/changeset/changeset.html:49 -msgid "No children" -msgstr "Нет дочерних репозиториев" - -#: rhodecode/templates/changeset/changeset.html:62 -#: rhodecode/templates/changeset/changeset_file_comment.html:20 -#: rhodecode/templates/changeset/changeset_range.html:44 +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 msgid "Changeset status" msgstr "Статут изменений" -#: rhodecode/templates/changeset/changeset.html:67 -#: rhodecode/templates/changeset/diff_block.html:22 +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 msgid "Raw diff" -msgstr "Сравнение без форматирования" - -#: rhodecode/templates/changeset/changeset.html:68 +msgstr "Отобразить в формате diff" + +#: kallithea/templates/changeset/changeset.html:58 msgid "Patch diff" msgstr "Применить разностное исправление (Patch diff)" -#: rhodecode/templates/changeset/changeset.html:69 -#: rhodecode/templates/changeset/diff_block.html:23 +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 msgid "Download diff" msgstr "Скачать diff" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "%d комментарий" -msgstr[1] "%d комментариев" -msgstr[2] "%d комментария" - -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +msgstr[1] "%d комментария" +msgstr[2] "%d комментариев" + +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "(%d inline)" msgid_plural "(%d inline)" -msgstr[0] "(%d в строке)" -msgstr[1] "(%d в строках)" -msgstr[2] "(%d в строках)" - -#: rhodecode/templates/changeset/changeset.html:103 -#: rhodecode/templates/changeset/changeset_range.html:82 +msgstr[0] "(%d к строке)" +msgstr[1] "(%d к строкам)" +msgstr[2] "(%d к строкам)" + +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 msgid "merge" msgstr "свести" -#: rhodecode/templates/changeset/changeset.html:126 -#: rhodecode/templates/compare/compare_diff.html:40 -#: rhodecode/templates/pullrequests/pullrequest_show.html:113 +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 #, python-format msgid "%s file changed" msgid_plural "%s files changed" @@ -3797,9 +4796,9 @@ msgstr[0] "%s файл изменён" msgstr[1] "%s файлов изменено" msgstr[2] "%s файла изменено" -#: rhodecode/templates/changeset/changeset.html:128 -#: rhodecode/templates/compare/compare_diff.html:42 -#: rhodecode/templates/pullrequests/pullrequest_show.html:115 +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 #, python-format msgid "%s file changed with %s insertions and %s deletions" msgid_plural "%s files changed with %s insertions and %s deletions" @@ -3807,417 +4806,448 @@ msgstr[0] "%s файл изменён: %s добавление, %s удаление" msgstr[1] "%s файла изменёно: %s добавления, %s удаления" msgstr[2] "%s файлов изменёно: %s добавлений, %s удалений" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Showing a huge diff might take some time and resources" msgstr "Отображение слишком большого diff'а может занять длительное время" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Show full diff" msgstr "Показать полный diff" -#: rhodecode/templates/changeset/changeset_file_comment.html:30 -#, python-format -msgid "Status change on pull request #%s" -msgstr "Изменение статуса Pull запрос #%s" - -#: rhodecode/templates/changeset/changeset_file_comment.html:32 +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 +#, python-format +msgid "Vote on pull request #%s" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 #, python-format msgid "Comment on pull request #%s" msgstr "Комментарий в Pull запросе #%s" -#: rhodecode/templates/changeset/changeset_file_comment.html:55 +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Status change on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Comment on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:63 msgid "Submitting..." msgstr "Применение..." -#: rhodecode/templates/changeset/changeset_file_comment.html:58 +#: kallithea/templates/changeset/changeset_file_comment.html:66 msgid "Commenting on line {1}." -msgstr "Комментирование строки {1}." - -#: rhodecode/templates/changeset/changeset_file_comment.html:59 -#: rhodecode/templates/changeset/changeset_file_comment.html:145 +msgstr "Комментарий к строке {1}." + +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 #, python-format msgid "Comments parsed using %s syntax with %s support." -msgstr "Парсинг комментариев выполнен с использованием синтаксиса %s с поддержкой %s." - -#: rhodecode/templates/changeset/changeset_file_comment.html:61 -#: rhodecode/templates/changeset/changeset_file_comment.html:147 -msgid "" -"Use @username inside this text to send notification to this RhodeCode user" -msgstr "Используйте @имя_пользователя в тексте, чтобы отправить оповещение указанному пользователю RhodeCode" - -#: rhodecode/templates/changeset/changeset_file_comment.html:65 -#: rhodecode/templates/changeset/changeset_file_comment.html:152 +msgstr "" +"Парсинг комментариев выполнен с использованием синтаксиса %s с поддержкой" +" %s." + +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "" +"Используйте @имя_пользователя в тексте, чтобы отправить оповещение " +"указанному пользователю Kallithea" + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 msgid "Preview" -msgstr "Превью" - -#: rhodecode/templates/changeset/changeset_file_comment.html:72 -#: rhodecode/templates/changeset/changeset_file_comment.html:170 +msgstr "Предпросмотр" + +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 msgid "Comment preview" -msgstr "Превью комментариев" - -#: rhodecode/templates/changeset/changeset_file_comment.html:80 -#: rhodecode/templates/changeset/changeset_file_comment.html:177 -#: rhodecode/templates/email_templates/changeset_comment.html:16 -#: rhodecode/templates/email_templates/pull_request_comment.html:16 +msgstr "Предварительный просмотр комментария" + +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 msgid "Comment" msgstr "Комментировать" -#: rhodecode/templates/changeset/changeset_file_comment.html:81 -msgid "Cancel" -msgstr "Отмена" - -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "You need to be logged in to comment." msgstr "Вам необходимо авторизоваться, чтобы оставлять комментарии" -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "Login now" msgstr "Авторизоваться сейчас" -#: rhodecode/templates/changeset/changeset_file_comment.html:92 +#: kallithea/templates/changeset/changeset_file_comment.html:100 msgid "Hide" msgstr "Скрыть" -#: rhodecode/templates/changeset/changeset_file_comment.html:149 -msgid "Change status" -msgstr "Изменить статус" - -#: rhodecode/templates/changeset/changeset_file_comment.html:179 -msgid "Comment and close" -msgstr "Комментировать и закрыть" - -#: rhodecode/templates/changeset/changeset_range.html:5 +#: kallithea/templates/changeset/changeset_file_comment.html:159 +msgid "Vote for pull request status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:161 +msgid "Change changeset status" +msgstr "Изменить статус ревизии" + +#: kallithea/templates/changeset/changeset_file_comment.html:179 +msgid "Close (when approved or rejected)" +msgstr "Закрыть (когда одобрен или отклонен)" + +#: kallithea/templates/changeset/changeset_range.html:5 #, python-format msgid "%s Changesets" msgstr "%s Изменения" -#: rhodecode/templates/changeset/changeset_range.html:52 +#: kallithea/templates/changeset/changeset_range.html:59 msgid "Files affected" msgstr "Затронутые файлы" -#: rhodecode/templates/changeset/diff_block.html:21 +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 msgid "Show full diff for this file" msgstr "Показать полный diff для этого файла" -#: rhodecode/templates/changeset/diff_block.html:29 +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Show full side-by-side diff for this file" +msgstr "Показать полный diff для этого файла" + +#: kallithea/templates/changeset/diff_block.html:38 msgid "Show inline comments" msgstr "Показать комментарии в строках" -#: rhodecode/templates/changeset/diff_block.html:53 +#: kallithea/templates/changeset/diff_block.html:62 msgid "Show file at latest version in this repo" msgstr "Показать последнюю версию файла в данном репозитории" -#: rhodecode/templates/changeset/diff_block.html:54 +#: kallithea/templates/changeset/diff_block.html:64 msgid "Show file at initial version in this repo" msgstr "Показать исходную версию файла в данном репозитории" -#: rhodecode/templates/compare/compare_cs.html:4 +#: kallithea/templates/compare/compare_cs.html:4 msgid "No changesets" msgstr "Нет изменений" -#: rhodecode/templates/compare/compare_cs.html:32 +#: kallithea/templates/compare/compare_cs.html:8 msgid "Ancestor" msgstr "Предок" -#: rhodecode/templates/compare/compare_diff.html:5 +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 #, python-format msgid "%s Compare" msgstr "%s Сравнить" -#: rhodecode/templates/compare/compare_diff.html:9 +#: kallithea/templates/compare/compare_diff.html:16 msgid "Compare revisions" msgstr "Сравнить ревизии" -#: rhodecode/templates/compare/compare_diff.html:33 -#: rhodecode/templates/pullrequests/pullrequest_show.html:106 +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 #, python-format msgid "Showing %s commit" msgid_plural "Showing %s commits" -msgstr[0] "Показать %s коммит" -msgstr[1] "Показать %s коммита" -msgstr[2] "Показать %s коммитов" - -#: rhodecode/templates/compare/compare_diff.html:48 -#: rhodecode/templates/pullrequests/pullrequest_show.html:121 +msgstr[0] "Показать %s commit" +msgstr[1] "Показать %s commit'а" +msgstr[2] "Показать %s commit'ов" + +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 msgid "No files" msgstr "Нет файлов" -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -msgid "confirm to show potentially huge diff" -msgstr "Подтвердите необходимость показа огромного списка сравнения" - -#: rhodecode/templates/data_table/_dt_elements.html:54 -#: rhodecode/templates/summary/summary.html:69 +#: kallithea/templates/data_table/_dt_elements.html:63 msgid "Mercurial repository" msgstr "Репозиторий Mercurial" -#: rhodecode/templates/data_table/_dt_elements.html:56 -#: rhodecode/templates/summary/summary.html:72 +#: kallithea/templates/data_table/_dt_elements.html:65 msgid "Git repository" msgstr "Git репозиторий" -#: rhodecode/templates/data_table/_dt_elements.html:74 -#, python-format -msgid "Fork of %s" -msgstr "Fork от %s" - -#: rhodecode/templates/data_table/_dt_elements.html:88 +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "Публичный репозиторий" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:96 msgid "No changesets yet" msgstr "Изменений ещё не было" -#: rhodecode/templates/data_table/_dt_elements.html:95 -#: rhodecode/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 #, python-format msgid "Subscribe to %s rss feed" msgstr "Подписаться на ленту RSS %s" -#: rhodecode/templates/data_table/_dt_elements.html:103 -#: rhodecode/templates/data_table/_dt_elements.html:105 +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 #, python-format msgid "Subscribe to %s atom feed" msgstr "Подписаться на ленту Atom %s" -#: rhodecode/templates/data_table/_dt_elements.html:122 -#, python-format -msgid "Confirm to delete this repository: %s" -msgstr "Подтвердите удаление этого репозитория: %s" - -#: rhodecode/templates/data_table/_dt_elements.html:137 -#, python-format -msgid "Confirm to delete this user: %s" -msgstr "Подтвердите удаление пользователя %s" - -#: rhodecode/templates/email_templates/changeset_comment.html:4 -#: rhodecode/templates/email_templates/pull_request.html:4 -#: rhodecode/templates/email_templates/pull_request_comment.html:4 -msgid "URL" -msgstr "URL" - -#: rhodecode/templates/email_templates/changeset_comment.html:6 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:6 #, python-format msgid "%s commented on a %s changeset." msgstr "прокомментирован %s в наборе изменений %s." -#: rhodecode/templates/email_templates/changeset_comment.html:14 +#: kallithea/templates/email_templates/changeset_comment.html:9 msgid "The changeset status was changed to" msgstr "Состояние набора изменений изменено на" -#: rhodecode/templates/email_templates/main.html:8 -msgid "This is a notification from RhodeCode." -msgstr "Это уведомление от RhodeCode" - -#: rhodecode/templates/email_templates/password_reset.html:4 +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." +msgstr "Это уведомление от Kallithea" + +#: kallithea/templates/email_templates/password_reset.html:4 #, python-format msgid "Hello %s" msgstr "Здравствуйте, %s" -#: rhodecode/templates/email_templates/password_reset.html:5 +#: kallithea/templates/email_templates/password_reset.html:5 msgid "We received a request to create a new password for your account." msgstr "Мы отправили запрос на создание нового пароля для вашего аккаунта." -#: rhodecode/templates/email_templates/password_reset.html:6 +#: kallithea/templates/email_templates/password_reset.html:6 msgid "You can generate it by clicking following URL" msgstr "Вы можете заново сгенерировать его, перейдя по следующей ссылке" -#: rhodecode/templates/email_templates/password_reset.html:10 +#: kallithea/templates/email_templates/password_reset.html:10 msgid "Please ignore this email if you did not request a new password ." -msgstr "Пожалуйста, проигнорируйте данное сообщение, если вы не запрашивали новый пароль." - -#: rhodecode/templates/email_templates/pull_request.html:6 +msgstr "" +"Пожалуйста, проигнорируйте данное сообщение, если вы не запрашивали новый" +" пароль." + +#: kallithea/templates/email_templates/pull_request.html:6 #, python-format msgid "" -"%s opened a pull request for repository %s and wants you to review changes." -msgstr "%s открыл pull-request для репозитория %s и просит вас просмотреть изменения" - -#: rhodecode/templates/email_templates/pull_request.html:8 -#: rhodecode/templates/pullrequests/pullrequest.html:34 -#: rhodecode/templates/pullrequests/pullrequest_data.html:14 -#: rhodecode/templates/pullrequests/pullrequest_show.html:25 +"%s opened a pull request for repository %s and wants you to review " +"changes." +msgstr "" +"%s открыл pull-request для репозитория %s и просит вас просмотреть " +"изменения" + +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 msgid "Title" msgstr "Заголовок" -#: rhodecode/templates/email_templates/pull_request_comment.html:6 +#: kallithea/templates/email_templates/pull_request_comment.html:6 #, python-format msgid "%s commented on pull request \"%s\"" msgstr "%s оставил комментарий к pull-request'у \"%s\"" -#: rhodecode/templates/email_templates/pull_request_comment.html:10 +#: kallithea/templates/email_templates/pull_request_comment.html:10 msgid "Pull request was closed with status" msgstr "Pull-request был закрыт со статусом" -#: rhodecode/templates/email_templates/pull_request_comment.html:12 +#: kallithea/templates/email_templates/pull_request_comment.html:12 msgid "Pull request changed status" msgstr "Статус pull-request'а был изменен" -#: rhodecode/templates/email_templates/registration.html:6 +#: kallithea/templates/email_templates/registration.html:6 msgid "View this user here" msgstr "Подробнее о пользователе" -#: rhodecode/templates/errors/error_document.html:55 +#: kallithea/templates/errors/error_document.html:47 #, python-format msgid "You will be redirected to %s in %s seconds" msgstr "Вы будете посланы на %s через %s секунд" -#: rhodecode/templates/files/file_diff.html:4 +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 +msgid "File diff" +msgstr "Сравнение файлов " + +#: kallithea/templates/files/diff_2way.html:58 +msgid "ignore white space" +msgstr "игнорировать пробелы" + +#: kallithea/templates/files/diff_2way.html:59 +msgid "turn on edit mode" +msgstr "включить режим редактирования" + +#: kallithea/templates/files/file_diff.html:4 #, python-format msgid "%s File Diff" msgstr "Сравнение файла %s" -#: rhodecode/templates/files/file_diff.html:8 -msgid "File diff" -msgstr "Сравнение файлов " - -#: rhodecode/templates/files/files.html:4 -#: rhodecode/templates/files/files.html:76 +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 #, python-format msgid "%s Files" msgstr "%s Файлы" -#: rhodecode/templates/files/files.html:30 -#: rhodecode/templates/files/files_add.html:31 -#: rhodecode/templates/files/files_edit.html:31 -msgid "Branch" -msgstr "Ветка" - -#: rhodecode/templates/files/files_add.html:4 +#: kallithea/templates/files/files_add.html:4 #, python-format msgid "%s Files Add" msgstr "%s Файлов добавлено" -#: rhodecode/templates/files/files_add.html:19 -msgid "Add file" +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" msgstr "Добавить файл" -#: rhodecode/templates/files/files_add.html:43 -msgid "File Name" -msgstr "Имя файла" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:56 -msgid "or" -msgstr "или" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:52 -msgid "Upload file" -msgstr "Загрузить файл" - -#: rhodecode/templates/files/files_add.html:56 -msgid "Create new file" -msgstr "Создать файл" - -#: rhodecode/templates/files/files_add.html:61 -#: rhodecode/templates/files/files_edit.html:37 -#: rhodecode/templates/files/files_ypjax.html:3 +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 msgid "Location" msgstr "Расположение" -#: rhodecode/templates/files/files_add.html:65 -msgid "use / to separate directories" -msgstr "используйте / для разделения директорий" - -#: rhodecode/templates/files/files_add.html:79 -#: rhodecode/templates/files/files_edit.html:65 +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 +msgid "or" +msgstr "или" + +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:58 +msgid "New file mode" +msgstr "Режим нового файла" + +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 msgid "Commit changes" msgstr "Применить изменения" -#: rhodecode/templates/files/files_browser.html:13 -msgid "View" -msgstr "Просмотр" - -#: rhodecode/templates/files/files_browser.html:14 +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:14 msgid "Previous revision" msgstr "Предыдущая ревизия" -#: rhodecode/templates/files/files_browser.html:16 +#: kallithea/templates/files/files_browser.html:16 msgid "Next revision" msgstr "Следующая ревизия" -#: rhodecode/templates/files/files_browser.html:23 +#: kallithea/templates/files/files_browser.html:22 msgid "Follow current branch" msgstr "Отслеживать данную ветку" -#: rhodecode/templates/files/files_browser.html:27 -msgid "Search file list" -msgstr "Искать файлы" - -#: rhodecode/templates/files/files_browser.html:35 +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:29 msgid "Loading file list..." msgstr "Загружается список файлов..." -#: rhodecode/templates/files/files_browser.html:48 +#: kallithea/templates/files/files_browser.html:42 msgid "Size" msgstr "Размер" -#: rhodecode/templates/files/files_browser.html:49 +#: kallithea/templates/files/files_browser.html:43 msgid "Mimetype" msgstr "Тип файла" -#: rhodecode/templates/files/files_browser.html:50 +#: kallithea/templates/files/files_browser.html:44 msgid "Last Revision" msgstr "Последняя версия" -#: rhodecode/templates/files/files_browser.html:51 +#: kallithea/templates/files/files_browser.html:45 msgid "Last modified" msgstr "Последнее изменение" -#: rhodecode/templates/files/files_browser.html:52 +#: kallithea/templates/files/files_browser.html:46 msgid "Last committer" msgstr "Автор последнего commit'а" -#: rhodecode/templates/files/files_edit.html:4 -#, python-format -msgid "%s Files Edit" -msgstr "%s Файлов отредактировано" - -#: rhodecode/templates/files/files_edit.html:19 +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:25 msgid "Edit file" msgstr "Редактировать файл" -#: rhodecode/templates/files/files_edit.html:47 -#: rhodecode/templates/files/files_source.html:23 -msgid "Show annotation" -msgstr "Показать примечание" - -#: rhodecode/templates/files/files_edit.html:49 -#: rhodecode/templates/files/files_source.html:26 -msgid "Download as raw" -msgstr "Скачать в .raw формате" - -#: rhodecode/templates/files/files_edit.html:52 +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:58 msgid "Source" msgstr "Исходный код" -#: rhodecode/templates/files/files_edit.html:57 +#: kallithea/templates/files/files_edit.html:63 msgid "Editing file" msgstr "Редактирование файла" -#: rhodecode/templates/files/files_history_box.html:2 -msgid "History" -msgstr "История" - -#: rhodecode/templates/files/files_history_box.html:9 -msgid "Diff to revision" -msgstr "разница с ревизией" - -#: rhodecode/templates/files/files_history_box.html:10 -msgid "Show at revision" -msgstr "показать в ревизии" - -#: rhodecode/templates/files/files_history_box.html:11 -msgid "Show full history" -msgstr "Показать полную историю" - -#: rhodecode/templates/files/files_history_box.html:16 +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 #, python-format msgid "%s author" msgid_plural "%s authors" @@ -4225,219 +5255,223 @@ msgstr[0] "%s автор" msgstr[1] "%s авторов" msgstr[2] "%s автора" -#: rhodecode/templates/files/files_source.html:6 -msgid "Load file history" -msgstr "Загрузить историю фалов" - -#: rhodecode/templates/files/files_source.html:21 -msgid "Show source" -msgstr "Показать исходный код" - -#: rhodecode/templates/files/files_source.html:29 -#, python-format -msgid "Edit on branch:%s" -msgstr "Редактировать в ветке: %s" - -#: rhodecode/templates/files/files_source.html:31 -msgid "Edit on branch:?" -msgstr "Редактировать в ветке:?" - -#: rhodecode/templates/files/files_source.html:31 +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:8 +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:11 +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" +msgstr "" + +#: kallithea/templates/files/files_source.html:38 +#, python-format +msgid "Edit on Branch:%s" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "" + +#: kallithea/templates/files/files_source.html:44 msgid "Editing files allowed only when on branch head revision" -msgstr "Редактирование файлов разрешено только в последней версии ветки" - -#: rhodecode/templates/files/files_source.html:46 +msgstr "Редактирование файлов разрешено только в HEAD-ревизии данной ветки" + +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:61 #, python-format msgid "Binary file (%s)" msgstr "Бинарный файл (%s)" -#: rhodecode/templates/files/files_source.html:55 +#: kallithea/templates/files/files_source.html:71 msgid "File is too big to display" msgstr "Файл слишком большой для отображения" -#: rhodecode/templates/files/files_ypjax.html:5 +#: kallithea/templates/files/files_ypjax.html:5 msgid "annotation" msgstr "аннотация" -#: rhodecode/templates/files/files_ypjax.html:15 -msgid "Go back" -msgstr "Назад" - -#: rhodecode/templates/files/files_ypjax.html:16 +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:24 msgid "No files at given path" msgstr "По заданному пути файлы отсутствуют" -#: rhodecode/templates/followers/followers.html:5 +#: kallithea/templates/followers/followers.html:5 #, python-format msgid "%s Followers" msgstr "%s Наблюдатели" -#: rhodecode/templates/followers/followers.html:9 -#: rhodecode/templates/summary/summary.html:183 -#: rhodecode/templates/summary/summary.html:184 +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 msgid "Followers" msgstr "Наблюдатели" -#: rhodecode/templates/followers/followers_data.html:12 +#: kallithea/templates/followers/followers_data.html:12 msgid "Started following -" msgstr "Наблюдать за репозиторием" -#: rhodecode/templates/forks/fork.html:5 -#, python-format -msgid "%s Fork" -msgstr "Форк %s" - -#: rhodecode/templates/forks/fork.html:28 +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:30 msgid "Fork name" msgstr "Имя форка" -#: rhodecode/templates/forks/fork.html:65 +#: kallithea/templates/forks/fork.html:71 msgid "Private" -msgstr "Частный" - -#: rhodecode/templates/forks/fork.html:74 +msgstr "Приватный" + +#: kallithea/templates/forks/fork.html:80 msgid "Copy permissions" -msgstr "Права копирования" - -#: rhodecode/templates/forks/fork.html:78 +msgstr "Скопировать привилегии" + +#: kallithea/templates/forks/fork.html:84 msgid "Copy permissions from forked repository" msgstr "Скопировать привилегии с форкнутого репозитория" -#: rhodecode/templates/forks/fork.html:84 +#: kallithea/templates/forks/fork.html:90 msgid "Update after clone" msgstr "Обновлять после клонирования" -#: rhodecode/templates/forks/fork.html:88 +#: kallithea/templates/forks/fork.html:94 msgid "Checkout source after making a clone" msgstr "Скачивать исходники после создания клона" -#: rhodecode/templates/forks/fork.html:93 -msgid "Fork this repository" -msgstr "Форкнуть репозиторий" - -#: rhodecode/templates/forks/forks.html:5 +#: kallithea/templates/forks/fork.html:99 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 #, python-format msgid "%s Forks" msgstr "Форки %s" -#: rhodecode/templates/forks/forks.html:9 -#: rhodecode/templates/summary/summary.html:189 -#: rhodecode/templates/summary/summary.html:190 +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 msgid "Forks" msgstr "Ответвления" -#: rhodecode/templates/forks/forks_data.html:17 +#: kallithea/templates/forks/forks_data.html:17 msgid "Forked" msgstr "Форкнуто" -#: rhodecode/templates/forks/forks_data.html:42 +#: kallithea/templates/forks/forks_data.html:42 msgid "There are no forks yet" msgstr "Форки ещё не созданы" -#: rhodecode/templates/journal/journal.html:21 +#: kallithea/templates/journal/journal.html:24 msgid "ATOM journal feed" msgstr "Лента журнала ATOM" -#: rhodecode/templates/journal/journal.html:22 +#: kallithea/templates/journal/journal.html:25 msgid "RSS journal feed" msgstr "Лента журнала RSS" -#: rhodecode/templates/journal/journal.html:32 -msgid "Refresh" -msgstr "Обновить" - -#: rhodecode/templates/journal/journal.html:35 -#: rhodecode/templates/journal/public_journal.html:24 -msgid "ATOM feed" -msgstr "ATOM лента" - -#: rhodecode/templates/journal/journal.html:51 -msgid "Watched" -msgstr "Просмотрено" - -#: rhodecode/templates/journal/journal_data.html:55 +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "Мои репозитории" + +#: kallithea/templates/journal/journal_data.html:55 msgid "No entries yet" msgstr "Записи отсуствуют" -#: rhodecode/templates/journal/public_journal.html:4 -#: rhodecode/templates/journal/public_journal.html:21 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 msgid "Public Journal" msgstr "Публичный журнал" -#: rhodecode/templates/journal/public_journal.html:13 +#: kallithea/templates/journal/public_journal.html:16 msgid "ATOM public journal feed" msgstr "Общая лента журнала ATOM" -#: rhodecode/templates/journal/public_journal.html:14 +#: kallithea/templates/journal/public_journal.html:17 msgid "RSS public journal feed" msgstr "Общая лента журнала RSS" -#: rhodecode/templates/pullrequests/pullrequest.html:4 -#: rhodecode/templates/pullrequests/pullrequest.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 msgid "New pull request" msgstr "Новый pull запрос" -#: rhodecode/templates/pullrequests/pullrequest.html:25 -msgid "Create new pull request" -msgstr "Создать новый Pull запрос" - -#: rhodecode/templates/pullrequests/pullrequest.html:47 +#: kallithea/templates/pullrequests/pullrequest.html:44 msgid "Write a short description on this pull request" msgstr "Написать короткое писание по этому запросу" -#: rhodecode/templates/pullrequests/pullrequest.html:53 +#: kallithea/templates/pullrequests/pullrequest.html:50 msgid "Changeset flow" msgstr "Поток изменений" -#: rhodecode/templates/pullrequests/pullrequest.html:60 -#: rhodecode/templates/pullrequests/pullrequest_show.html:65 +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 msgid "Origin repository" msgstr "Первоначальный репозиторий" -#: rhodecode/templates/pullrequests/pullrequest.html:85 -msgid "Send pull request" -msgstr "Отправить pull запрос" - -#: rhodecode/templates/pullrequests/pullrequest.html:94 -#: rhodecode/templates/pullrequests/pullrequest_show.html:137 +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 msgid "Pull request reviewers" msgstr "Рецензенты запросов на внесение изменений Pull request" -#: rhodecode/templates/pullrequests/pullrequest.html:103 -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 msgid "owner" msgstr "владелец" -#: rhodecode/templates/pullrequests/pullrequest.html:115 +#: kallithea/templates/pullrequests/pullrequest.html:114 msgid "Add reviewer to this pull request." msgstr "Добавить рецензента в данный запрос на внесение изменений" -#: rhodecode/templates/pullrequests/pullrequest.html:129 +#: kallithea/templates/pullrequests/pullrequest.html:128 msgid "Detailed compare view" msgstr "Детальное сравнение" -#: rhodecode/templates/pullrequests/pullrequest.html:150 +#: kallithea/templates/pullrequests/pullrequest.html:149 msgid "Destination repository" msgstr "Репозиторий назначения" -#: rhodecode/templates/pullrequests/pullrequest_show.html:4 +#: kallithea/templates/pullrequests/pullrequest_show.html:4 #, python-format msgid "%s Pull Request #%s" msgstr "%s Запрос на внесение изменений #%s" -#: rhodecode/templates/pullrequests/pullrequest_show.html:35 +#: kallithea/templates/pullrequests/pullrequest_show.html:36 msgid "Review status" msgstr "Состояние рассмотрения" -#: rhodecode/templates/pullrequests/pullrequest_show.html:40 -msgid "Pull request status" -msgstr "Статус pull-запроса" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 +msgid "Pull request status calculated from votes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:56 msgid "Still not reviewed by" msgstr "Еще не рассмотренный" -#: rhodecode/templates/pullrequests/pullrequest_show.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:60 #, python-format msgid "%d reviewer" msgid_plural "%d reviewers" @@ -4445,241 +5479,256 @@ msgstr[0] "%d рецензент" msgstr[1] "%d рецензента" msgstr[2] "%d рецензентов" -#: rhodecode/templates/pullrequests/pullrequest_show.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:62 msgid "Pull request was reviewed by all reviewers" msgstr "Запрос на внесение изменений был рассмотрен всеми рецензентами." -#: rhodecode/templates/pullrequests/pullrequest_show.html:89 -msgid "Created on" -msgstr "Создано" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:102 +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 +msgid "Pull changes" +msgstr "Pull изменения" + +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "reviewer" +msgstr "рецензент" + +#: kallithea/templates/pullrequests/pullrequest_show.html:133 +msgid "Add or remove reviewer to this pull request." +msgstr "Добавить или удалить рецензента данного запроса на внесение изменений" + +#: kallithea/templates/pullrequests/pullrequest_show.html:137 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 msgid "Compare view" msgstr "Сравнение" -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 -msgid "reviewer" -msgstr "рецензент" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:164 -msgid "Add or remove reviewer to this pull request." -msgstr "Добавить или удалить рецензента данного запроса на внесение изменений" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:168 -msgid "Save changes" -msgstr "Сохранить изменения" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:4 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 #, python-format msgid "%s Pull Requests" msgstr "%s Запросы на внесение изменений" -#: rhodecode/templates/search/search.html:6 -msgid "Search repository" -msgstr "Искать в репозитории: %s" - -#: rhodecode/templates/search/search.html:8 -#: rhodecode/templates/search/search.html:16 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 +#, python-format +msgid "Pull requests from %s" +msgstr "Pull запросы от %s" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 +#, python-format +msgid "Pull requests to %s" +msgstr "Pull запросы для %s" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 +msgid "Hide closed pull requests" +msgstr "Скрыть закрытые pull запросы" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 +msgid "Show closed pull requests too" +msgstr "Показать закрытые pull запросы" + +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 msgid "Search in all repositories" -msgstr "Искать по всем репозиториям" - -#: rhodecode/templates/search/search.html:50 +msgstr "Поиск по всем репозиториям" + +#: kallithea/templates/search/search.html:53 msgid "Search term" -msgstr "Искать термин" - -#: rhodecode/templates/search/search.html:62 +msgstr "Фраза для поиска" + +#: kallithea/templates/search/search.html:65 msgid "Search in" -msgstr "Искать в" - -#: rhodecode/templates/search/search.html:65 +msgstr "Критерий поиска:" + +#: kallithea/templates/search/search.html:68 msgid "File contents" -msgstr "Содержимое файла" - -#: rhodecode/templates/search/search.html:66 +msgstr "Содержимое файлов" + +#: kallithea/templates/search/search.html:69 msgid "Commit messages" -msgstr "Сообщения коммита" - -#: rhodecode/templates/search/search.html:67 +msgstr "Сообщения commit'а" + +#: kallithea/templates/search/search.html:70 msgid "File names" msgstr "Имя файла" -#: rhodecode/templates/search/search_commit.html:35 -#: rhodecode/templates/search/search_content.html:21 -#: rhodecode/templates/search/search_path.html:15 +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 msgid "Permission denied" -msgstr "Нет прав" - -#: rhodecode/templates/summary/summary.html:4 +msgstr "Недостаточно прав" + +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 +#, python-format +msgid "%s ATOM feed" +msgstr "ATOM лента репозитория %s" + +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 +#, python-format +msgid "%s RSS feed" +msgstr "RSS лента репозитория %s" + +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "Включено" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "Полученная статистика:" + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "файлы" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "Показать еще" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "commit'ы" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "файлы добавлены" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "файлы изменены" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "файлы удалены" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "commit" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "файл удалён" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "файл изменён" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "файл удалён" + +#: kallithea/templates/summary/summary.html:4 #, python-format msgid "%s Summary" msgstr "%s общие сведения" -#: rhodecode/templates/summary/summary.html:16 -#, python-format -msgid "%s ATOM feed" -msgstr "ATOM лента репозитория %s" - -#: rhodecode/templates/summary/summary.html:17 -#, python-format -msgid "%s RSS feed" -msgstr "RSS лента репозитория %s" - -#: rhodecode/templates/summary/summary.html:62 +#: kallithea/templates/summary/summary.html:16 #, python-format msgid "Repository locked by %s" msgstr "Репозитарий заблокирован %s" -#: rhodecode/templates/summary/summary.html:64 +#: kallithea/templates/summary/summary.html:18 msgid "Repository unlocked" msgstr "Репозиторий разблокирован" -#: rhodecode/templates/summary/summary.html:83 -#, python-format -msgid "Non changable ID %s" -msgstr "Неизменяемый ID %s" - -#: rhodecode/templates/summary/summary.html:88 -msgid "Public" -msgstr "Общедоступный" - -#: rhodecode/templates/summary/summary.html:88 -#: rhodecode/templates/summary/summary.html:89 -msgid "Fork of" -msgstr "Форк от" - -#: rhodecode/templates/summary/summary.html:97 -msgid "Remote clone" -msgstr "Удаленный клон" - -#: rhodecode/templates/summary/summary.html:117 -msgid "Contact" -msgstr "Контакты" - -#: rhodecode/templates/summary/summary.html:131 +#: kallithea/templates/summary/summary.html:76 msgid "Clone url" msgstr "Ссылка для клонирования" -#: rhodecode/templates/summary/summary.html:136 +#: kallithea/templates/summary/summary.html:81 msgid "Show by Name" msgstr "Показать по имени" -#: rhodecode/templates/summary/summary.html:137 +#: kallithea/templates/summary/summary.html:82 msgid "Show by ID" msgstr "Показать по ID" -#: rhodecode/templates/summary/summary.html:143 +#: kallithea/templates/summary/summary.html:99 msgid "Trending files" msgstr "Популярные файлы" -#: rhodecode/templates/summary/summary.html:151 -#: rhodecode/templates/summary/summary.html:167 -msgid "Enable" -msgstr "Включено" - -#: rhodecode/templates/summary/summary.html:159 +#: kallithea/templates/summary/summary.html:115 msgid "Download" msgstr "Скачать" -#: rhodecode/templates/summary/summary.html:163 +#: kallithea/templates/summary/summary.html:119 msgid "There are no downloads yet" msgstr "Скачиваний ещё нет" -#: rhodecode/templates/summary/summary.html:165 +#: kallithea/templates/summary/summary.html:121 msgid "Downloads are disabled for this repository" msgstr "Скачивание отключено в этом репозитории" -#: rhodecode/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:127 msgid "Download as zip" msgstr "Скачать в zip" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "Check this to download archive with subrepos" msgstr "Отметьте для скачивания архива с дочерними репозиториями" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "with subrepos" msgstr "с дочерними репозиториями" -#: rhodecode/templates/summary/summary.html:197 +#: kallithea/templates/summary/summary.html:163 msgid "Repository Size" msgstr "Размер репозитория" -#: rhodecode/templates/summary/summary.html:204 -#: rhodecode/templates/summary/summary.html:206 +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 msgid "Feed" msgstr "Лента новостей" -#: rhodecode/templates/summary/summary.html:224 -msgid "Commit activity by day / author" -msgstr "Активность изменений по дням/авторам" - -#: rhodecode/templates/summary/summary.html:232 -msgid "enable" -msgstr "включить" - -#: rhodecode/templates/summary/summary.html:235 -msgid "Stats gathered: " -msgstr "Полученная статистика:" - -#: rhodecode/templates/summary/summary.html:256 +#: kallithea/templates/summary/summary.html:193 msgid "Latest changes" msgstr "Последние изменения" -#: rhodecode/templates/summary/summary.html:258 +#: kallithea/templates/summary/summary.html:195 msgid "Quick start" msgstr "Быстрый старт" -#: rhodecode/templates/summary/summary.html:272 -#, python-format -msgid "Readme file from revision %s" -msgstr "Readme файл из ревизии %s" - -#: rhodecode/templates/summary/summary.html:332 +#: kallithea/templates/summary/summary.html:209 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:299 #, python-format msgid "Download %s as %s" msgstr "Скачать %s как %s" -#: rhodecode/templates/summary/summary.html:379 -msgid "files" -msgstr "файлы" - -#: rhodecode/templates/summary/summary.html:689 -msgid "commits" -msgstr "правки" - -#: rhodecode/templates/summary/summary.html:690 -msgid "files added" -msgstr "файлы добавлены" - -#: rhodecode/templates/summary/summary.html:691 -msgid "files changed" -msgstr "файлы изменены" - -#: rhodecode/templates/summary/summary.html:692 -msgid "files removed" -msgstr "файлы удалены" - -#: rhodecode/templates/summary/summary.html:694 -msgid "commit" -msgstr "правка" - -#: rhodecode/templates/summary/summary.html:695 -msgid "file added" -msgstr "файл удалён" - -#: rhodecode/templates/summary/summary.html:696 -msgid "file changed" -msgstr "файл изменён" - -#: rhodecode/templates/summary/summary.html:697 -msgid "file removed" -msgstr "файл удалён" - -#: rhodecode/templates/tags/tags.html:5 +#: kallithea/templates/tags/tags.html:5 #, python-format msgid "%s Tags" msgstr "%s Меток" -#: rhodecode/templates/tags/tags.html:26 +#: kallithea/templates/tags/tags.html:29 msgid "Compare tags" msgstr "Сравнить метки" + diff --git a/rhodecode/i18n/zh_CN/LC_MESSAGES/rhodecode.mo b/kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.mo rename from rhodecode/i18n/zh_CN/LC_MESSAGES/rhodecode.mo rename to kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.mo index 9a90446b2a56cc99dcafc69d7946722f23fcf9c1..7b342309ae4b347b9703bb402af368f6146f4996 GIT binary patch literal 76104 zc%1Eh2Yi%8`v2nTshkSxiHdDSB5;xbXFKscMVg^VBmq%G++;V&!e%#aA%rG12@pt7 zdI#w(AP`Ct5WTba-W%CXa)PK>P*MNSGvDWJn+*i4_xtNd^6b=i=9y=nd7fvUnR)N5 z6KB}yziUpk*)Amb%%wKVeyqX|akxKAp zg5wD`A^14KGYGy%ura~?1pi9#2ZCo2JiD{ab{@gYJ0t$a&d8TSupvQLXS5?*;7Edh z;r2*)roaaYo=$M1l-t!A-+xllKM=T|;Q0iVkGTyWsmFf)^1S(*^ijMDSFCg2M=A5}el+^__T&&DNdZX#{5z>~{*nLUut-UH)wc@OmesvfAXi-ddi zKtCM zk>_s;>b+6oyGZ_|6wI$X2sUSWk@#sTpo6(mZo9zUDd@*z1lw^tQh=8W`hY&W^+9`j z_d$Qs`kI3|&?E|`eLdw0@2knaV0UdrS;Zysf{Mmhhr)GUIAFk_*@AT{o zeB4d&UjzdL6L~!P0)L15g73uLPCSJ1aXaSC_}kIGO}C@pPu`CC`N{3Vk0pF|Kj8ne ze#rl?erR7`f>gE5*AMkS)(`D{QQ+JCz`w%%fVY$HKz(Nrq$z8=_zsyLcVJ!(A(+kW zx&!$5@(#4)dx94bJnK%BPqaD$YqxD)k0dnf4V)jNT| zDhVID6YXi(AKyKNB0LIZj0OK@o0O;@G0l@Fx0cht*cccDhcY`i( zx*PrT-;Mb@?rz{=t-!LoK}S#D4f=my!k^!b`Sa(2$amI2#5Ws=eAf&F9uo&*+;1BQ zI=*WlzV9ChJQPd$bpp#J-!lU-ZXZd#9}h%3e;f#WHogb+bJ0C0*WwA?5yc7P5u9H`Ih!1snZFt73*z~e#(+EXU+ z&q#Q$1O5NPfqtHxiuT2&qF+}N{0G7Asi=Q^D#{n9qWsEKd~bUy=;=RF?sZAupNe+= zkP7-fISt`U(vZJp8ot+FV7D~Pn>*964rHdGeGd@KCAcCD__8~J&p0Q_wQ=IRH%fdT zC+Z*QME~z~f^Mfe(cTh**Yfx|u?~LW#CN}y^iy2G>p3p;<3b6?yD$z{N&KBI;BBxA z^fA!|`DMA}J0l(Q^{RBVr(-(Sr9SDPxBJr3{`_>bZx+FL#%DU(9g%W>$^bkk1M{gx z2GYA`h`g48aS2I$VFuRC)fxES`x%($r)DDlx=hShpTGw)f$wdZn3o@AVt)O_jdk@( zH`+Cj;FScYxRJg`;%fw+I|%8W2jM%pgTO~h24Q^uJqUF4)*$phG6?wjL$+p+PU42cI}b) z$0YoLA9xA-rCkK`xm|wrb7TN`ni@d;iv!5FJ^;LJ4uFmyBRGrTUV{A^(0B)t{z?e_ zs0yK;?*%p*0y@5w;7yFbA;8y^A?V-IA>cz#Nce*xpszpYpdHO}fTuP&$aifH%J<4a z{mvY$^FwkV5APw^f#82~(5{n*q909%qM!Dm7{_))fzKO;0x!1=#rX9eit)Nf(tQ#? zY$)(sAnDU2ym%=3y;|zsJrwPGTFQSQ`92;Bx#^3c7>_G+!Ds%Fi*dXqSLAyMJ95$g z%v|(8lnZ(vDR6o&+PyXx-`|=G{5?&OmR8$m1aBmmGz{%89wzI~Fyt>AhI(HdhW5TG z@RMQq?w^LE-HnHXZ=5f%*KqV}!f<@QcsTGncet$kl3q3(czR6IUzPNT)ce(N;Ni#N zkn>I)fpzqv5lFvr1n_yw2;e1U1lpZG0{s~=0`*Oj@Z1sj-l`F3|F#jJ|9_9b_urH9 z2PFSVBk`THN21(?Bf*UPY)M};5_Gmz>Um-$+WorJ zzjq|YYu`w;<4>bd{;#8u|MF32=hdUozFwoik6e;(^eB|SU&5{3pR~1g|2P zKN{m-J{t9ZJ{s-$b~O5V+8E5+bH-r4wHpIH^x82i~2{71^woY1)rEV7VGS0$@lJ9@Sj6tF~6=G z2R?DrIE2TJL%$}D!*`}h_(6ed#{n;!$6>r49tU~wErO(a+O8ZAI>;N3@^d7-c09`O z8jp5AHXil7G#+&S{&?W!kie5Cp#CNkK#y%FpuXEC03T@+Q2yQtm@lIyV4N3EfZVWY z0_2}pCty4dPJo=zC=d9(F%Nj@n}__P^T3~%<)QxP^DsW|=3#se=AoXG^O1g8KIUD! ze6+ViKKhlEk9ORZ5Bz84V_YWW%es<}dKc$ooJ#XS$4}>j4quS)r;`86e9+s;1&|AG zC_ukM1*m6i0q{DzK=^P0zQ4Kv?b%s?aeb@+^z&>1`twEs=wY9fKY1eB+h`*6p%xR- z-&-f*dxIvTeK`}sKW9w@f7l}NFH8P|6Va|llK|r;!H#nMB#cLnz!{U!p3MZWW4a*d z;qjjYeZw^wuwXLAckN{8W6w?o-aelU{G42faX7ya?Qd0xavciMPiG<8JCxup{M|yd z^F4xHdEOR6j=Xsa=+rv}>0_nQvx)|5V7ee=S14ZYTm?dl#YHy+!CpK@q+)zX;`DlzcS=X{oZE zQjC1#ib0>Viot)D7o+`aCB3{D^Xdi3_updB%^`wa2sW4|a=??d;%T7Ug%bau#BU^cFUfPerhyLIPDgvLoi5**4t(~Wj{as%7ky6h6$@N49s1@& z)4`8Fm2mtFn~hX*+u#|PhfmHxJKmUqad>wI@O5AY`hD_DjPs>4fsd`5^ML>E^MKER^FSZYd8l`=lp8S*-ybjem(2rRZ=Wao z4D&F5pOkW6O1?kOM}L~m7kj~c%$M%-fzLtn(T;-o!1K)c==a9?z~_?!BlE$3{5+7J|-BUj#nZd=cb-&m!dCwg~d?>x+PgYZjyZw=G6L2QS8W zj$e%Q#RAI~qu$p9?q3Z2owx*iy6F=1J7o#%FS$!F?hh>iebp>M{f(DG|7*1rcqm?q z`L&1OMxMU}Zzs6qLC9O*Jc$0cScdVvVj1YW-7>V}re&D7w@dt>Wx!AFGT?jEGL)ac z40v6<407I@Wx&Tb%P_CbUygZw`Et;Ao8_RFPRoJ!e#^x^Bl+%?^kK^}PE(ho9dnms z9Xa2I*JK6o{I?a5Kf0^{K8LITy%b7#?F!VtX9dRb*%cU%^H!q# zl`BzyF9~~AqI|(h;R7pCzH}w*9FMF7-oILjdD3DP_`}~-*WPGj0c%HWg-??}V!dI@r zcwM&!<97qWdkOYmgLXZ;2IKMJ8uYt*4e08mwU|d2uZ0|YIYCl!Z5eA(-}`G(-`=(O zPJ?xzyOY;J4!>p{=xy>ktRFkpK|c9<9rjkkc+Jf!)7<3Gh--0{L=%3F?2N1oP&z67b=c8&U4ojTqOwjiAHj8^K?; z5$r+mO@g;^zc+!-hi<~SjNJq}pT7z9m2bj$f3yjBKkXsl@zRGtFaLT7@jV{`zEdSU zA2Qdd%A_`o(6@ z*@F@;k@P)M?wQS?gO@gA+~3@cdHmsKjK?Pu-*gMgHQR!4{1$xg>MdBOuiJup61T`c z)E3a`9b3RhMo76aTR}GZmIwAEuyywe18ktxo->l@%a|u=LdnOZN+z+Zbdzp zZbi9PTfslB*$RF#a4YKZOZw2Qm{$|F0x#>fVtv~s;pe5k4<%f)75(~dtH=?hXiuY3 zOM$03rKo=)K@#h1tEK!p`QAek z-c^cz{kv4`oTXy-kb1r<1zx@rc)~V(=hSUzSCeh1r{y-ZD?#A3+t9w7wxL|NZK&_I zZIBE5O8E!2VSQRI`QMZH>TPKMw*&_<{cb0kB$&M&?LW93?fh{&zTapE+JDXtS+{p! zTwCox`n3dKZ9u$W2g;va2D-eY41A}18R%?S8Ti2hflrlTUVmK%K68FK%HLIvdNT!j z1qKBUD@S`qOSnkj3@Jaa9C%z=4t#A9SRv&elYFlV{IDGO*k2C*e@MzVssOyO0{o>_ zh1h>3zDEV{bVmj1byuLip%vg8<10X~vn76Y1^DvT3h<$qD=;pfR>=N_)PKq@z%zG= zy>ge>L3W{@D|Ug;UAqhTyL}hvELZXu?!q|VzYFW%GKqh67yLEeCODd4i{0q&DuKIq zqrI=~#`mgrqaB}1{CB%i&uI^X?#_A`^XmME(T__XM*b@vM*gcFM!lUMM!CDBTKb`@DYsTHp&0$BWV9e60Ug! z`2Xq=8P7)%KJ!uVoy#6Y{uYlSf5M}nhwC53`1E@e{u;|3g}+9}f5Ttn^?w7e+5dsR z#+d(LeS7;q;FBjkhIPF4V~~$BAH#Y({xRs`C68epdqL8_d<^ULnUAA?9UjL#O?w>a zd5q(4*?@7?ns3#$p&3F>{TmK~1k1bNqyHDafhn~dvp7a#vOVg)N?((P5 zo_|Sv*QZcV@>AezcS?BRQ}}+mgtMOlo#i|Qd`yyhN}d88Y?pkm34He{;Gyy<_`Ce+ zY4E{oo(6rop2j$4J&ksadK&$l`8391`P0D9<4@zel~V5Or_sM3CI4y9pq&>ygK*q4 zz|&RFpj`K7K<{@y1AKU&!M?+|XP}=x@(jLr%Co5FZ_mPCu65fPB}#0DgJ%3&2zA3t~5w@F)pS z5jgh+%-5AKV4QYH_$f($=LPWxdI96~gQQ>ZBIZT>i^w-X;Gh?gKj%fXv+zaWb=8ZQ zmk+-Px%a~tK~Lwu1U_@^OTcT=OOR&=zl3trUP3*qUjm;0^Ag7AZ7KKdOPEJzzYP3d z^D^@Fdl~h6UxvR%;mc^>F3I=w%QC(KzkeBg_4HT7Ui6CCi(Zlam{*W5MW9pi1z!<9 z{0hdk=oNf_&MWwS$t!68v#$XEHB$bNuc7>s*U-OJ62Ij&%&R@GVZ7gX zP3$ZZ|L4~czUXy~bHeNBXUEskKF90m*S)Vp9?O3n-+B0T@lTcV@4b%i9e5q|boh1P z^Ncr;e(4)1_xCptf1QMTNP6-cG7bWRZ(!bxe*=8$ekr%@4cJkhdINl~)0-Hl#5eK% zo3frr{ukZ^{k|*VbKb&to4ti_+qclp8zkIG!neJJap))U zId1`PT>$|W=bra})7j$+1yRtsL z3pwN6chR1c-UEMa_a5|%f$t&x0f{dYSR?7@zK`#8e;?yF=6$ql`um{MHSc4-mA;R0 z+4a8YW$#07-6!S#`~mQK{s$QMt3MDwV}V^IJ>>(8d-ez5JHtKzeiuu=l^?)gW6KAS zXF7g}{9Qkkas5#Ejl_FDgulkn55>RgBedt*k3@g@2y*IeAEExS9|_<12>Ito{?#90 zew9nP7e5lajD!z<1ita@N3y@VSNyB@0#6t1MZQ*h(f_u4QQy^jL9gBR!d};JFXX=6 zd(oc%NV%8xVw~RG3w$@IL_bfhgulimmB2@nDvW>AD#+3QtU~#&Rial)xL*~3ecwja1d8&c8KsD$)uNwXu4_3opi03mE9+ydM+-j&os@ozdfxdM?fCp-wByH* z#U8y6<(uw9{cZMPo$s&@cpJJ8`>-SSp{<1%T{6F&(_-lOh3EI=_0Qks14j}9}fO0tp z(2h|DfUl_sKwnD^p#N(RfNzuv+;>3yXg)>0HlHGV-KVIhi-h|MO#4*y4M`s(aN4J` zPJW91toju6zUNc%bNCea+$Z%M`V{Rx=`+l;3qC_Vtt5QiXBd~RpP^lSCHmo2&((m~k^$q$Q zc$oM(#(A!kTPOL-KS%o>`yBk}ozKzkuRq5+((oY4U3w7odgVcsyY?XZ)8QcIK`%+q zlk`akf#>N5VaK0$5dIqfJt%%+U*J2peS!7D`32g4{}-?eFZu%O#|Hxc`la|6eJTD$ zUt+u*UxM!s`V!yG`x18IV#y!=663S)OVt0}mzd9|d?otxSF)~uCH}czph4OMz!p8E#h`{Enm z<@9eMXI%R&^!xtbqTal3K^G5vi}6|gE$XTG7X5kiTYPWdw;0dEQtmI`iQe=b%D4PZ z^yKeEE|Bn@6+;`xM4@&-3-=Tk71-|l~tj|)i_81t+7 zVZ>i8@i!j^JtZDS`%@01e8ypn%gDp1f5Ks`Q_BvczfT_qJyjhB-aeD~hTqFMukTUc zjRJdrk9u9-0}sQ$haF||_mD>)7a0Ct^wb}qN1Xlx{587$fOT-&570ZF{{j5)^B+K8 zfBg}7yY5HO*R4MafBO;N&Hho&w@CbIiQn-f{577J@OicdYM(QKAj^?M2y*_V1Uda7 zflm-*JibSe+x;;?<=5JvfszB76J$S%4h@h#gdn$TIzgt}6%u}&prRXs-2Q!%-rxk3 zYetaqc@se%hdWNd_lKTHTO1?t`d7tn{f;=wWPDFaji3q0>RO|YQz{gO56C~gLC!(Ik62DU57J}@r zu}9LcJQ?k2e=^d$pNxL=Bgp(cN8+bSzIg)I5#;@`3W7{8-%0o%r!-Lh8beM&xmQlX zcRoA?c&{eN^z`j1==WKt0-vo<1wL*h$n!6mpgJE#ko`6CPDMRGo{D<^+z|LbyCLE` zH3YqMZ;15%4e`CqhUmwzhWOsJhQQm}hUn)u3BM-rqlW0;CldZq>ix@KQ2v6yfIhA! z$owjqAj>Z!2{PYV@fXnHR!M*9FQBi(f5Et&c^cYx0YRR(El)!`J4v`NL6&Fyr-80l zod!C5^fc7-&S_}(XOh41=?xUWY<)V~opd_ta}eZpH$af>VQWqYo<0@$_35CK9|WFu z2JqkX45TLry!s5(`%i+*mwKLo_VhUec<~ZsId+ufA5T#2FP?#UvGEMF=dm-;pEu4x zyAMh|jT!-;EgPY}E&}^D0zT6lp?s(j@S5KU<(4(VcvKK%KK;7He@&42Q{%?K)88AT z{@WUZUVM#ZUNlC3RuW|XUeXxjv!yY{eOF`9;Zu_TIf1V>#`oSK$oo2n8w3A0o(Vcj zI}?0t7(teEA2}2KIpM4ZO3pd!EPTgt7U+Jkz)=FHN&2$0fUgY_e)25T|FY!!FF}@j zzCR22YO9O9-;RM(=YPD0yqm zIq3fz=b+#3oP&PsJqPVLcn;dpunFQXYJz<6P4K;|nxK4A6SP023HpC`6O7Y(iGPeB zug5P)J#RL_xYtO1hnisgf0TS@o-1^EF2*V0T$F21kma>*=YszH=c0YH&c%FNBjvW8 zi}pQDkmZZ2b3vzPohS40JcK))hx+e4596GE9>!y};Crh!5$*u zbRo+1yb%3Pxe()c?}aEo=|a%Wbb{=!@rdMae-ZG~;Ud(3&qd(tPJ-(E?nNk9eG%4= zCKoqQ@=40Yh%dev zjJ2blMRt_iYDar(>=@TmE=9QcrJ%!(67F*;=68@F+wrzsigEaJGt}3p8OAZL8Svk} z8Tds1W~k@BW*FCL%|I`!CI5Cwe^%i8%`l#yNw~>n82^@+fgU;v>~$IH>n|{H8S+oQ z4D~O#4E3+O4CAs#;1ic&e4oDze86I}7Y1&?V`iIMg#D4)_@#hjsjcILxbZg6#kByySa{Aj{!z#bJCKT#kO9dpYWD zemUyBO2XGmxVwaVUk<#cO1xKK=yJi!<-qso%YognGC?Q%&yITAmz1-_dv z`HKb4YJv51VGGdPgHnEb3(Tjdq9bHcZbL04raO>u`>tg(pKog>HL4F*)xfO!l@M^H`Mgf!mx|1FIs6)=hyagry36I{pB++q_0$75`+S459R9&7)6IT|H!ahp zes@#@@9||A0ips+0Qr1b*$yTj`ssH$f^KgHwJ+Nja0h+}!vh2i9(4|~rG+Fj+ zkINBo+5I7}N}&op?lcGYgND>WOo;yX`JFC58Wl)$c#Vb#+D#2J(-JeG7$l~m^@x^n z%<4RDud9{ycbdl+a5-Dq;^XbNQdb>}w88fHcw0Ngg4%)ev=i2Hwa#riBqiDhyNEd{ zwlIh?c^w{14Hc6eN~In~C8YX7L0gA3?zRF$2zA_HUMCDLtT1qI$nAI8laqU>QOphn zGMPiDpOnv=kzh|uSIKEiAL)!t7mrt#I}qTUJUnhi3qfiD_3M_Dlq7p+zn`kOs_ixH zRc||_rMa?$j#Q5;0qt?wm}SsE;#O{t)83WQs=~Jtl`tPs0b_1Q1x*F|5dQTarg-Y6 zok$prUPTazWl|PxA>cS##x$s?NCgy$W%-7So#Naf-j5K znl%2DFGSL;1H4zUVROzbhd1Q#)R~QBVMaJ{SDFECj(2DnaSv0I*5z>qxFIG~5OW~J zE57SXOAGl~=yrxwEon3yO!Pw>9=B7zQ)gZ!Br=}U@twM}Y7zoxB_XC>`OIr8No4gb z1%_4MoErD5D?eCaz%hgZb>|`mc(g2Lsy}L8=Hp6Y;k6~mq?&e=p-_tujr`F^!h}^8 zD>&*%144_8Pi3N-jXuZ$}PqUj^ zWizHOCcLdfwwom=dmyC3=`;|znm8FdQ4v&KiHe6&QnsHY1j<8tfiC`$DBx65s<{NR z1aq@p>KCin+Q?gi_9Raz!_7>^8l9}kmK~ssbTF|Qjc@Qsx`vXb?KRknt-}zaa~8Vn zsUf!~7|+9{eL_#la%H8mhDI?#(nZxu>vRV=&1t*Y?R79sv1DZWZEqPDXl2t>Q~d|i zoT0DYOwyJOE4l!ct}XF5hgj}Y6C#jC!_2w3l}uDUU49y7H+6+&jDS6!knUhziI91- zbj8-O7E?1}9jO5VL>3(KvVP$pI?oVc0Sgl;7OWi;vLp+JUTH)@;!wP-kkTF`&4Ex8 z405ebHOB&42{oBq<`s$s>0GuSxIF3n1&5N6Iy$nclMWlybGt*~o9fge3`-6(#!x_u z*9csKz8o)cI2!J#$(W#J;4kYdOEz^mhx8q5V$`R#R5m7v@c??MSz?5zwq~%+OKGS?^w}OqF7T@C9QCRxAtAwLvbd<9if5{}!$M#( z(ishh$Y6(FXzhlm!QDO3~)rK-U~W^O>b(oC2g1<*!{ zXHh3WB#=h*mrmS*1QC^2HN)$&DP@eNgNRiWR$?0FipD8Al8Vh5ug3)i6GKCqm6EX? zW^GCzwSdpholkRlor;z%@lIFm1Tgjl`yIZJJ&PnCX1heRX7$yq$x}aE+S(y&700-g zx{?H zNUHVfm2t)TM`(~z-K0@@^{RL@Z5@3ck0VIg)AEryxDC7?AjMr4v&ThwZ)CHiYssK>Onr^@H)m)0~Um!Kmf zkf7)1kRA{;d(++iEEwf=jxUkSGO(zr`O%e?_&U;*U<@7{JA)EKkCZ`i3eKR9oOua3 z<}z+qonLZiAE_N?%B(Ao(Xu1eWGECz%N3ojizY6!%&c@Vb2jF4bzn*LLTKBfJFqR@ zoKehGN;dXl-4t7Q?M$k@4oJ4qO&0z92syx)t?kXu6(LF%3bTTYR6{mWVgvU?N<^#j z3DG5LRUw$*N#?TH)YSHd%P=6C!XSEtll(A;TH>I^Sfh*`2`vs&AHR97Wtj3?X%=w? z?PyU>4cd9(l%E#UdF)v9Id&?LZb~Bt(cT_dDgr|*+ZS8w(h#vs zR<`Ux(tN~^Og(Thd_pCn<@;natQ3X+EC&X#c_zUGCxXF)_D==bH?eIDM* z4RVuMSJOKrikqp6q|%Xw%leA3j`AibGr8XSmo-JWlh50N6&&K9B+6;p)r}MnD$#$a z&98v!t}dqs?7ba1mhdolwh>k`o))qy;EF114Z5CH*V8+5Ut#6r-di{1%!b=ElHI+U z@*y@EsLo29cR3Sy8%5VO{4TVR>tymzQ=&gU#G6tHHnmmEf51G|uO!2yq{6kfZB(ox za`lTo54o#7p^aneBs5NB3Q9F>5mr@6%b-_&JoMI?#UT9Uoo(KNkPykW>F%Kja9nmU z*E}+vy*wNO3`I?8n94k%Hk}oNNr=uB&>}K3NS7l9p|}#;bi8O3QauiTh6^34oklA& z@6^lA9e)yQsy)Rt()!j2Z;it0%{&+?iP+-QN(GA?b$`fgh%n{ibwz?Ep`=y} zHOfnfs0&F>4eBPc&R*7D<6369y{+6VBKaLey?!MvtG#MuaM(!%3%O!tB;_w7D!0?% zGptNG#OjJf#yM|0vo4L8Kqf1%9!IK+h(%c^)3g=TEPg8f8I^8jj7Wr4TIs0f2)`@M zo$Xf2Qs>wPd!^*mm1wf&#}XNiUP==l>Y4K>HP^8faFkMNUC};OM;?|)j+Q3?D}z-# zh@BM+Iycj)t%x8;%HN93&1$-wMC}#X-G)#_tES(b;leg7SO(W>5wuftHTMW8>n>+&)Xu#O z@K~s1?z$+>RKn@gstj<${TV((zao)RVw9!c8a-J3ffPz4km@o%!@EnS%?y=KutvXp z>3|j;)f%Jti;7ZXXmY&iq7-cb(QaM=tr-1f4K*>z)+I^}vvo~Op>_rFLj)UJSEY)1 zY)We6KbF;(7g-hQai`OILH$r6HoFUt3Anv!YCFTOh>RUvAnhgCmAycrPcxlBbY;tO zTuY|vR%YRr6?thDJ{q9EX2XQ7tH+nhO;y06$i-Cqy87%lJJJRd^kvZG>_Ge^R|z?3 zJ`$n2`epki_8 z^H1%Q?kskaR^Bpfw;h^|tp(j9vNq-Xgf@6xLE>Gi74$QQnS{1Vw2=>G`miNY*Ff5! z_^H44W^pZ*ATf|RRI5NUng(oF$)$c^`l(!s{o|+C_$dsoD~xK&*U(|zE~lzIS+-kT zMDEO-ZehKJ|HRs9qhudd&3}}_LBH6prT!|eovKDxt=U0Z4Kf&~;(ErLA}&Ag46|Pu z?_m%Z$W%<27`wfV`VgyLu3S}>Rz4{=n9260kXNh7Z`!&y28@*JMD8wi%$=>AF1@zI zB<8wig_mLs-@L>$mMIf6ytFtY+8)TJ*=$S9;@uPAH%kAw(UwRZVV_xt#f!`l(A*%z z-fD;l%ue;)af})7F$Kl?kjj;%8GDwZck*tZk^xc!K4pheRs|}jmw}+5fkB>GL`lwwfM=H03%VmT}Z6v7-TY16Q-i9wl-FU%%i@iq463OfUv?=oCL3@%Cfb4UKx?&U=*^YYfw3Yj;gv)4T_fGr$x94) z5;a>P@O;rvU7#xbCirvDEb&W@2H4=#97+P+reY}*z2Aqgp z4zp_AlBBA5Mh5x7t0|^T3_LHCJ1{XRk{yGv(K+nBJ9p^RvolO(+-x>! zSj`y3L%O?i`JY|W3?QE}qmW%>nu|PYtwE{*TJ_obt(G^x-5bK5Kh*&9zG_igh=`+y zGJN!KK&94=XFVKLEgT~7yN8cd1N>AhUH$59$*vuT@FVCkN@V#+0df2nIiF1+_JPEa6C{#k;lPK>q?AO!=X}` z4~ugUeE_6RVlEXQtp1o~NDgy16tE^_*b}`1c$nh?D$pwwR1li9+6ZJf06srtil$LA zM^h8Lq$A-M)n)btvh~!QPLJp`hFqRp^Y*1NGoqc2?7e6uQ`(v+P%#{lWkl5R3!{2{ zqtR4?eWkE_&gM7a=DJLyCRk7QGsFCJI8{i{De8z;ny}bY`KxfCk7*ySr+Bd#K4zUY zJE}R-G(tUHK}URwBZDbIqbDn{8+%*@LatCd0sCf8fV$%uJ`ONHFo zmJ0P1!W`gM@?N$>|ANIB$PsD;aB|VFWgBYj6xwd}$?-S(p$UVzuAmAU?%L8>k_t&S z2M@DmP#B0x*0`GSlMoVwjmC&$KQl{6`@EQr_@@%CSij}7oJf^}Wm-@(XluU%`VXbQ z5W5q8b}PGA1=%e{-1xKzeQ!m@U|wmpd(ET?=P*ezIRlWO;r60yX02MHwE})cZ1V90 z#F&gydbBql7*Tr*Zm!kKox@_|%2D4@i%W(Q7&+u>uT4SaKo$u3buTid)}&#xPaPXj zQ<{VjD#kt6pt*16*?4P6<34IfTr=3=B&<4`W;!L4;deV(a!hBzouafIPPekT<#-d0 zUR{<$YBNqp*0aK(k8m)=6(#cYVn561Q@*id)ykl4AexD^7fuVN<`Q*KKnR~Dy8eLy zN<>x69nNXylL5M&QOScex_V)JhL#Bt^4acIdm&-T*C>>G9Hpr7q_4Rxo6NnmZF~Na z!-BD)QRx=wUhJQ1OJa96K2J@vko~nZ?;ZVHW@{I?nv(KJdSp@~B})nKX+96zS;YY? zNn>c*529@L$V-aJ+w@pC^?2Og!Lj1>Wtulf;7Tb|+sdM~qC|Q=IjqS(+e!QvR_Y`d z(Ua!EW;1O9Cz)rwmswqsX)!YW#+)$tZW4)IL|a+(LrqebZ0bQkjEdCReN;T;{=}pq zSFu2wnBDgpqfh3XQQbw78@jaN9cOo^E2Yaxb;A2wj=x)+@9Z>KYNt{_z#i8U%(#`D zuWjk2HDzGXH;|(#GL^Uq+i_Ul*R8sWJttw$IZ0e96=aLGz8)p{-Rdl}I5ycV4o>Dk z06xL8;iIMS0SEXCh=;mpoeA2(1G80M5sM4kw`r1H*<4JkrB<_aJZT}1L$@{z z@daH`IhETztaxyGkI^X3BOg+ohOQ9n!%-pK#$kKe1xowV!b)LJoBL^(Dw<{jZN@sSxbpp#a=Ce6gr$>r( zIMtslm)H!@8*zY(3$Xi5Z&y11!L=R6hNd3l)dXZU0M>()>Hws9x3qqxvZD1;Dd(>p zFgHkf_Ys6wJ^jdXWSjOHIRXkG@zCCC$OI@Ut~czAmP6ta2lrI#gh!H7gC^?@TMq^;h4*~94aN={Hrts=@g6h$(Xlq!l@C4PGn0f`y;AeX;_BE`jP{{3 zJa0@>qOL41Zyh;e>}A%kU7PirND zr+}bMswOk0+AgxODvE)u=(L~w4OKql2vbi##~ULmCLXl37_G0>jEp1j6D>6cH_?(} z@)F}(1nQZxHP<=eVic+a2N|_UP4iEzgDd5#Gl(=hy-`FfC+a+~!kQ8g1L?>duezZ1 zKywR`J-4WAP9tC49gT_4qfEa#5DiZfYgP-|kGQ#NE@VZ!^(L4hX{PhqdUC+(p6YRv zzK2s}@HXPjA>|hY#|Bp4wUg}hspP)5Mrj3XN_S`Qu{KeAsV2h+%Z65F4{F~qYJJ3B zVz!JwtHHhXGo#{WiU?&@O)})AT5%%c!Ahjbl==pRegI63@{m9)?J^QzmABTEQ=jDo zpdU^;rjxG8J!PjFzjXNxA=3KrOLoiEZ*~Wv(J%rjJ(Bf+Uo9NT^cD3-yYveI-58O~ z?iUWVEu!tYsjZ)&Ka>WBmXTm@p?PVvZ_{QtS3UA3ZOgySa2~FaEn2fjiX0dpLUMik zpY9RzE4zcJe$fxjZ%heh8XkWJ--zRNjQ9zkRzpKS(nIF$O7NtgSgqSR(w^AK>QdS| z+986i%}ht2E%pa@6FtM{3ji0$@y?tU;r1H8YHza|NwK0yk;u}26F$=vzf6W{&p4kd z5mBxOig#N!Z?&~p-_}xsd_7BR%WeG&n>L=0@@YOfh~4;Fhu-1>);mXJp0`$vRJ$w3 zxH!qsJQAdKFm3N(3VNODkM*FNih*(ybOZ+L*JP;pY^(K9WkZVEl9ggUic+MnmIH5^ zO9_z4YGl|>CO7-QVxV1>V44@nnwtV=S0gPUarkHk%;sWvi((=pUB<;6f z|83f%R}my3C3ez(s(nEfi0M^TX9~M8BUM=-*nQ3G4)R*Bi4<7Gkpy8#C6E^D(%j$KwkeUuHVr!@;vNa*%dFCC?*rKf z4ot2qEx?KP_icTmcba-#+#b(QHF% zf}oi4z00J*XA`DIS6+Q%%$R(&cH7c@B+vQ@w|t*Wq8G4FwgxpUa#wgqMBQz{q4*po zHN%NUsm|J*jow~Q=B;4|u~_9spRPObMjr@F77u76M?A*`T{hFDr^e5tpD^US0egmn zIV2loR76O-G?a%cE)W%GxgsK2c?QbmIGQDvVtv_1>_x7}ot~?^J|5YQ6Lw?FCkugXBhxcx~xf*3o|vMU-h2iEku zQba4aq}Oq^vNe-t9m1I?+3>GBhdK-!GucosYjq#03 zG?t;D?)TjBR^2H}cbu@t%Z(69g@hI?*^TnLt2C*xLmVFFYc%xDG!3Ac`f~IYOxSRc z9S{<1Qq+Z0ymc)01hu!QqBZ$n@x+#?#F$#?EoJ3g_=X>oCEeaO{>s0zqaGhFsXP_3$<++YHsUDG5@QT=iqA3oaZfMjbA%@)1&( zbgOeJx;HuBR_&IvK)gfGx4Ph7W6e{PD2ir@2h&+^y!t%r$n?+aGhJoEUJ}+M*)6V} zqHTKBm7saOSkm;fw6&Aq*h0|>iWV(NzL;%O3v=ygwVQ9mDngK(2Gj++qQNBClZ=~) zFPd9+(t(+43Tj%oFVbGV|3a+OZaW4r!Ox)lo1IN;Mtst)m#X z!XnXNnDvD)LC>aq&}DC3c?p@181tceu2q@(<8=tJ#{^)Dcj_RLgr@w-K6+f3o=*o!zkN!_>!239N@? z)*MH!0n03be&+-3x4X4_MDDlf$nVjM;e_i zg_Jcf-wqA`kQ7?;V|W*(kP;Lf<(JdBa4Ab+Crkblb+DBU4@xObu=VNPga7gPQ4{*W zE5X=-j5XUUb*#ozDV+x$MneifuAv`;y~Kp{ zyV;bhs1|A3YNa?PJ^|*%wU1`q)qYqK;V7#7800tPZ(QFdQD%=?T{^e7%+wC(wvvoO zkD9itMaDdit0lteUkjO?O0~FHdz&%R44;V@*NAHQt%r`a*gDSs_Q}rh^L5Z}8Vp+1 zoXS_8V$~@>bt4eF&EKTcv>cAbT^FK1DJLik1Jv%}HYTzX?6@lJC||(xxP?kGb<|}( zGHl#Y9%EZ8R-(3_V@iv)YhWZRYl{(--EjB!?O+R@rf{~?dszz@` zm~vV+qx#e~m6_v=trSzFd9TD2ZQ0^5yMdd2M_YGPQp`=*KH4o`eKZ5S_CxDx9h)w7 zWpf8iHvsCH%z3PAR?m_}E01=NLpfbLJlP}|g|b|J8d1|(9OF<&pfyvD+vikTFFT29 z8!!-4S>6U^#H>m!0eWSsCFoZS{4xI|)?(|ce8!9whSw%_XNq!$=u00Uea~%Dv;)S$ zA|-F>J4$LTjk@VP!LHp-g#y}AtqmRDt!6P9+4}MZk71nSg^uEwnb`XJaMzM`BS$uG zRAQ|A4sTa}(N5d#E@donvu}q(&!I0>(cXc&)l+6t0#(q$&$bFbA1WvP!gSlQtByOA zbqNzk?V_xxBHVj?88|(r=!9Kh&Bu}WyQ#L@A)RWHnzH-yE{!w9jOTWqLHNs(Po{QZ zr+!h2=HX!0SZ|N9H6Fb#1hmu7wQof+Zk#b0c5QqWC~rZ?EnZ4UqNQIQ?1n8~GcB-S zpykGC1mj*Uxn)pai&I@N9zm3q`+%&aUD|a;$5ggOP`#sLqBopbcL!T=pF>K5RAlW9 z^2V!a*)>(+vQ$xL!g1AYz7X&@DsdWjVp&Ieh(68Knc6z@1}rlK3|q76>Rv?kDs6G% zHr*lM%_W9Oq9=(=_xDo8v-i7Cd8-W7_FXFp;fuM`dLGl zs}|KA<27MEgGj#;R|;525+PK$c7ZqvHM za(jl^+uebO#$x7BiF$imTbZ`5H3r0Zq&O}%!S2vcZXI0-tC#*|>)#Vku??{G$3Dt{ zT1PG@MSEy!K&{m&M!L?ntfw0K8^%z}WorXK=a!t<4IFT^NbMk=DN%7RYfz?We=uij zrDBzciWKt>$7>2!)VT^R5+ zRdpoGRH!2on6U%}Gq^XN*ptm+>>4r`h88T_pSDzoQ}e~QK^8Dw{cTg(cmm2{vZPHcbJl7a+hG-;ocuHPcgLx5^V0;cQq(Jjlc2~ z8wD8I+J*JX=nr)@t|iIoq$KbTC1;B|U$4jLe9>(_2Cp<2P36`d&Q-T~lVuPNcIMbb ziVnK7Z64EkYVAIFQWR)`V$xFG*SAkOk5}PFzYkvBwZlq*&FhO28e*>Gejl9nK>A*v z&cgx}@Vac;rQ(Dm;&;kF*rs1BOcbB(;WNjzTmW)yQTB#=l~=yeb#=HH18sxl&t|bz z)skgxcojr{1X4eoV>B2O%Erg<)E~8t>9qUQGXnfeFLT7yfDIcTxu*TL=!0yTj(~R6 z>5U8{hWt_IB5`Z~Kq_E%nY zMO*r>A>XVJpCTXi`P&o9{b?jBg@zH^4h(kN|A~m3veikJ_*9ZT`BtNUQAuw`h(wn7 z6qh5bJ-_5fT*zf_$v+&e>@ArKwr|rWCnqOCb;_OY8p{VpQM##%PA%@b7N%U+DK86{#jd`WsyIgXKTZG6T({ye~y=GF()IlmWOxG;#nyX z;R)-)6E>Nm@l0*xfhj~Zzq@B@3F}qUSJ}c#7ltP-{^ee(jchBU`oj}e)r?zJvt&or zybVWutCmKdDFt+YOmEfJjGkM)J733Y)x0f{smt+o5MJf>NtNY`rD`M?m1Sj> z6*CAyHRCFXEzrCU&tGMpAv7FS^CuGn0gCmZ;P|=YpU%g>T z^amvq7*Bm0Q^zZ`mAe;Em&}Z--ZdI8(4vyaf^ju-ild8@EK$9Ce$}eU)!RzKyT*eT z*ZUi_-k4?cjMJDbD=jZ*J55$V_{c}7J z3-KpXP^=d4qrDAVxwEi(_q=dHDa3~Z=W$pY`Ux%&SK83{c z@Wwn@YRkqeirOi64M%1zj%=Qxv6b+=#gr7@Fb-yb@PyLJvYFIsOd1iFe&wfOp#Vh* z3c8fQByq&IVNtxYVlfp7FWV9xSEN4-8>Kd*TI9DGdUO3=gpJH!6PdV+roB;6|5Y`q zG%|Y3FY+F&{tX&Al7Pd@R#uNLtX{e{Qb5|`dT3>lMax;(nz|^waH#59?stx*;!0ItXe##e$T&RrKZM2Ca*ry+pkq)iT#za zU^^v0yt61W_5N_dEF-pN&J-i|7kc&;9j(q^BfrA)H-;CCwg!&=_A8Bbc*5qIS?g;( z{~9h@LyUtu16D5z{OZl&c?)ScK+`B{){uTzPrZuy?I*wVO6&3Pb|b5o6q0@-by`4W z#cozSGEC?zf*DI620zuBt2=o%?1uH3mySWMJ=u3FlX$e0paq-1*au5pps zyQ-G$JiZrQQG*!Sev21fr3^G{{4A@vRtxQ$6ZFcC*wm;8SS=MO2_2;oFKUF|1Eo($8VQ8q4Rehi zAXXQj(M*GjBe`m28C4jrcpyA+3Y3MP=Sfx64l&h?)Sve))yU*+)ms)oZ%~TD(zQ{- zy(PzQ^nxnPpC&BS{dy|0R_>hovp=3HHdr+m<9?a9Q)wY00<7FIQ7li9sVhlju34}& zvS4?u7gS+47R7~Bq{#e5^?5|KrffD(1B~Y{_IfJB{K(d#>Xik1M~{I_LO*cODSUq+ zuBN9&5beRN!U#(fp$*d7T2)rWGRdSxk$GDpGdI@b)l_o@qO1Q-UQR`K&?IOwali4~ zsga_h>fIZEu4hxLOIB2sRpOAMXRH zW@}bG-bt-mZDQ{7Myl8sR*VhjZLL|dRUgIbqWR$|GbCBY|M(w9MKvVHurjRHcL)J{ zM~?*=ks4F8WCyAK;hobdCn=|tIh;3vwJD|9bMXE`qxn*!S;;olE6J9CNDZ|+jD)H+ zv%*CWYTHfG@0?cedVsetH%_A^PaZMlec|=9s@AQL#LDfXdEa&Wl-RkrC!@>%M_xFE zfFEtP`{QX-^V6n+Ba={FKYac1qUrzSi>7QyoK7{IaA1>ws6I!@B>q1S^J&6W{S?# z>lstS|L1?~8Po9Y*=!^($*WpChDj9R%AI+pDA-w|^w03_2{lW~c!@12HCEM4W#NUB ztLAMF7Z*waLSog*jS^56J!?Hb<8!9c(8z-2k)6f$e$cdL^ju!Rf3NSE8i@MiHPhq1 z8u5?UO#gVzRNc=?S^@v7ec7%U0M^eA&tGMJ$CT9wS_as8XXi>TUH=D6YvvYL&nh~? z6Q(sQW|Bfdb(b*^+tTml3DZcyv~bbb%I#B04>{WNrQvzIB8&6?c)#?I_e+1p_e&w5 zgp1d*)9$Rrkr@RC$_r{1EbNfnF){H#`9#sRk)+H5#^xajudI#jng<=6YcS=}o-vIS z%rre@D%*}RpE8C1#x@1z+QL?fl5OFQ3#vs=L8Nd@)rQeki`G+(4 zRx^FWFZpb#*(_~~%pV;to+?|8rZ-E&D<3e@C?jEC!qCB4PB%SRYOaQND31DMDG(kW zT^=r&RlQ`D<+0N6q{Y=06`~EPWR7JsCtG~hD~E%MDQp1$RbMNunp4J}AePrkYeusd zfelU~;xwnM6X9tUm1WDU2~$_qj2^PkoY~F;-*S@K zLv;)N9rLrJQjc<16YsZrzdK5wRlaWO2*l6x=BTQYFa-o^o%)@>Fj}*uG`wl7;b|~q zV@-ZhECMHv2zN3TofNsTpB?t&XKvKDSR^-V6mS?IjUrrBLPhBpi(()konh~sUR|=B zx%&fah>^>Ye28BV&{)neSAa%9mScs@#JnTZcPW46QXgj z;fWWO>6d=b(|pvx8u$rsd7>UuAL@R|Gv+A`!`aNt;n=-0DqJ;v6Q5-k->2H?=AkmWmF0|U@8skdM_f5pf4I}aOON5rPF5xA^<*dfULu=Uh4Tt+ z^otc0(vWtKj%+DIEO!-$Eg3+8ikU2x#C~@Zr;n?)EDe{>u))>YR_p0a)^aL}q_@Dj z&Gh!B_*9zDyz(+_!ksvEX|HaIGG+4lw0NNW43BS`yh2UhuUK)kMQGMya~iZtNwXxB zl<@(q+6m#jIYd0BDBYBzM_D}E^jM+T-j>bFU++E5*tjvjmTBkXS0>B1p3n3M;II3l zrdjJYI~PWKTK(>x(Tt)FAtO_+x*pMFfq3m?(^x5n5bau9tD@t5IWs(AO!bEC^{M`s zels)5LZfv&YI|7P8x?CN=>O9%WEx0P2batok5pChS2M7|;zo2N3@vchVAoA)yDjF# z*Hg`0)50=MO^!8vj6yNlsnKZj=c$R*vf8_H7K4$|A;pjN=KSwIe+doj=Y9WDOgaGC z%a?*{>_E(4WtPg=T%(RZ;V*K^iC>)U`(<9h#K~yu8<>cbRrHT1FtyMA@dW0vRD1kS zU}E#G_7j+huPz)Hp0`DvUspyQGjHNaWGNi|5++is7Ok%?S^vjVn8*7RCTw;!5A2Fe zU2cQ1>W`-|V?TwdsUqrf9F3zM>+6@|+WBj~e~C|qiwnX#N^xQxhL&S}`Z7{DF|m`h zpN}#ZPYJJ|W$w@a$Io8^4YC=5K(yr#4n4J>yOiOvn$K$I{w*H4lpX5gsnR1uyI2|C zSoHJ1af#31@;c>J@Y_CUDHe6H0UhgemKu_d@}On7d~|r_WN~&bS#HwOObPaQyS!p4 zCuqz$5k-1EU)*6n_{Hw>(@XhA3GIN*fpSt}ln5%W8GP*QNUv9_i#=rfj*X;d3ut)E z{K)#HF(ezH;YO-L(uCFz|Ni{3+o{OTu$j$^AAZJ21r6yXWyunGZ|}@0`vX zHPu_kM|KwLm$%qZj<5Tfu)Jo$!kVSyBl8#WJlVFba>pjjG`_o%uu?v^W_B6Rmks0U zte)Kma3K)(+;K6UTmxi@f+K>y$#2>`p(=1v@CZ*nvU36qM0LFKX#SRVC4-8Bv73)0 z?wo3N%&XpAOg+JoXXGJdGM9o`THg_^Ub+^yU)c2fg~E9gv@3*7%irSa(S_#AhK~0s zNBRukF{<{Yb(W8HnlWCveTtq;5)yq*ce?o9zT#*#O{tA8vH$$>VB>K=*of^vl53Y$ zP2^Kp;ldp?6Q&%)lZ|qat8{XB(r%L8Y~p=Zy<&{+p%Hba=a+r6k(t!gg2;k#OwfvL z$rW$1hHqbQywpf}X+DGtCrHB(MswqSj`tajTb8i(Uccz*5E078I zL|Ak%B;(MsB}&}?kM)5@^G9o4M7m!2Iobh-|Nk95z-ZdbFW6>mC1dt5r{f10!=uaf4V$Xf zJAZ>G7jd(mH1;RGwFsq)o&F*P(<;l>k($RYW@_()?=Hm9DW3x+=CZKK;?8gNv|?4o zw5qcC^17ngZGuEh7N9qd3-4TE3+K)GT|BNR_wsF@T(e*)`)w=ZsD9gg)$~O?@#HM; z+~4qVMQAf5zsk+|a=DDi&A8o!6?1WAi5YurbsRajT%2b4;(~DyJ6IK1vXv0}6Q4ko zdvxZnvRXjcMLKE&-teRUH6A_`J$QBrtVP16Co;c*mKRySOdQdX6~-mW5rv`{IdFd< zAJ*6~H(WeTSwi@}0G9r%R^Csd6l+@;5a?NA1k%}Ic*By&;_Z}?i&ZR^c9JxMG8^;w zLNwgGBG;d4mGP}q5N6bsnPLz_O?qi5dd#mAnjL2`)69;u+L1KV)mX^NM5i4Ti1M^W z>*ct@FYp>+q=>paX@IRiuCp9qw-|-`W2gqijI7+5XWrn_t?{=0QBM-U+BAUg;L*)$ z{XyUZYR5#oa_BiR4`V+yh}mkbEjp%NuMFbr=3?ec1f%*Ok$h`Ge`o=mfhsXsJ1uQ8 z85zy-AjnuT(&t!@2#VJWAA z`AI<`MC{xB>Q4&tDH|dg^-_=xek`Vw7q#CNjCNtS`j{(kVWao#$!mR4&?s2fbAraZ zSGude@J_hU;xR$lL2|ZHZ)FKqkMWVf`n>}PQ3wN#_W&c4mzz_LTW%ZYAUYKgIHUFaQ7m diff --git a/rhodecode/i18n/zh_CN/LC_MESSAGES/rhodecode.po b/kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po rename from rhodecode/i18n/zh_CN/LC_MESSAGES/rhodecode.po rename to kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po --- a/rhodecode/i18n/zh_CN/LC_MESSAGES/rhodecode.po +++ b/kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po @@ -1,4642 +1,5619 @@ -# Translations template for RhodeCode. -# Copyright (C) 2013 Marcin Kuzminski RhodeCode -# This file is distributed under the same license as the RhodeCode project. +# Chinese (China) translations for Kallithea. +# Copyright (C) 2014 RhodeCode GmbH, and others. +# This file is distributed under the same license as the Kallithea project. # Translators: # FIRST AUTHOR , 2011 # mikespook , 2012 # xpol , 2012 msgid "" msgstr "" -"Project-Id-Version: RhodeCode\n" -"Report-Msgid-Bugs-To: marcin@maq.io\n" -"POT-Creation-Date: 2013-06-05 19:55+0200\n" -"PO-Revision-Date: 2013-06-02 13:22+0000\n" +"Project-Id-Version: Kallithea\n" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" +"PO-Revision-Date: 2014-02-13 14:34+0000\n" "Last-Translator: marcinkuzminski \n" -"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/RhodeCode/language/zh_CN/)\n" +"Language-Team: Chinese (China) " +"(http://www.transifex.com/projects/p/Kallithea/language/zh_CN/)\n" +"Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -"Language: zh_CN\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: rhodecode/controllers/changelog.py:149 + +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 +msgid "There are no changesets yet" +msgstr "还没有修订集" + +#: kallithea/controllers/changelog.py:186 msgid "All Branches" msgstr "所有分支" -#: rhodecode/controllers/changeset.py:84 +#: kallithea/controllers/changelog.py:189 +msgid "(closed)" +msgstr "" + +#: kallithea/controllers/changeset.py:87 msgid "Show white space" msgstr "" -#: rhodecode/controllers/changeset.py:91 rhodecode/controllers/changeset.py:98 +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 msgid "Ignore white space" msgstr "" -#: rhodecode/controllers/changeset.py:164 -#, python-format -msgid "%s line context" -msgstr "%s行上下文" - -#: rhodecode/controllers/changeset.py:345 -#: rhodecode/controllers/pullrequests.py:478 +#: kallithea/controllers/changeset.py:167 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 #, python-format msgid "Status change -> %s" msgstr "状态修改为%s" -#: rhodecode/controllers/changeset.py:376 +#: kallithea/controllers/changeset.py:386 msgid "" -"Changing status on a changeset associated with a closed pull request is not " -"allowed" -msgstr "" - -#: rhodecode/controllers/compare.py:74 -#: rhodecode/controllers/pullrequests.py:256 -msgid "There are no changesets yet" -msgstr "还没有修订集" - -#: rhodecode/controllers/error.py:69 +"Changing status on a changeset associated with a closed pull request is " +"not allowed" +msgstr "" + +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +msgid "Select changeset" +msgstr "" + +#: kallithea/controllers/error.py:72 msgid "Home page" msgstr "主页" -#: rhodecode/controllers/error.py:98 -msgid "" -"The request could not be understood by the server due to malformed syntax." +#: kallithea/controllers/error.py:101 +msgid "The request could not be understood by the server due to malformed syntax." msgstr "由于错误的语法,服务器无法对请求进行响应。" -#: rhodecode/controllers/error.py:101 +#: kallithea/controllers/error.py:104 msgid "Unauthorized access to resource" msgstr "未授权的资源访问" -#: rhodecode/controllers/error.py:103 +#: kallithea/controllers/error.py:106 msgid "You don't have permission to view this page" msgstr "无权访问该页面" -#: rhodecode/controllers/error.py:105 +#: kallithea/controllers/error.py:108 msgid "The resource could not be found" msgstr "资源未找到" -#: rhodecode/controllers/error.py:107 +#: kallithea/controllers/error.py:110 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." msgstr "服务进入非预期的混乱状态,这会阻止它对请求进行响应。" -#: rhodecode/controllers/feed.py:52 +#: kallithea/controllers/feed.py:55 #, python-format msgid "Changes on %s repository" msgstr "%s库的修改" -#: rhodecode/controllers/feed.py:53 +#: kallithea/controllers/feed.py:56 #, python-format msgid "%s %s feed" msgstr "%s %s订阅" -#: rhodecode/controllers/feed.py:86 -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Changeset was too big and was cut off..." msgstr "修订集太大已被截断......" -#: rhodecode/controllers/feed.py:90 +#: kallithea/controllers/feed.py:93 #, python-format msgid "%s committed on %s" msgstr "" -#: rhodecode/controllers/files.py:89 +#: kallithea/controllers/files.py:92 msgid "Click here to add new file" msgstr "" -#: rhodecode/controllers/files.py:90 -#, python-format -msgid "There are no files yet %s" -msgstr "还没有文件%s" - -#: rhodecode/controllers/files.py:271 rhodecode/controllers/files.py:339 +#: kallithea/controllers/files.py:93 +#, python-format +msgid "There are no files yet. %s" +msgstr "" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 #, python-format msgid "This repository is has been locked by %s on %s" msgstr "版本库由%s于%s锁定" -#: rhodecode/controllers/files.py:283 +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:346 +#, python-format +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "提交时发生错误" + +#: kallithea/controllers/files.py:373 msgid "You can only edit files with revision being a valid branch " msgstr "" -#: rhodecode/controllers/files.py:297 -#, python-format -msgid "Edited file %s via RhodeCode" -msgstr "" - -#: rhodecode/controllers/files.py:313 +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:403 msgid "No changes" msgstr "无变更" -#: rhodecode/controllers/files.py:322 rhodecode/controllers/files.py:394 +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 #, python-format msgid "Successfully committed to %s" msgstr "成功提交到%s" -#: rhodecode/controllers/files.py:327 rhodecode/controllers/files.py:405 -msgid "Error occurred during commit" -msgstr "提交时发生错误" - -#: rhodecode/controllers/files.py:351 -msgid "Added file via RhodeCode" -msgstr "" - -#: rhodecode/controllers/files.py:368 +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:461 msgid "No content" msgstr "无内容" -#: rhodecode/controllers/files.py:372 +#: kallithea/controllers/files.py:465 msgid "No filename" msgstr "无文件名" -#: rhodecode/controllers/files.py:397 +#: kallithea/controllers/files.py:490 msgid "Location must be relative path and must not contain .. in path" msgstr "" -#: rhodecode/controllers/files.py:431 +#: kallithea/controllers/files.py:524 msgid "Downloads disabled" msgstr "" -#: rhodecode/controllers/files.py:442 +#: kallithea/controllers/files.py:535 #, python-format msgid "Unknown revision %s" msgstr "未知版本%s" -#: rhodecode/controllers/files.py:444 +#: kallithea/controllers/files.py:537 msgid "Empty repository" msgstr "空版本库" -#: rhodecode/controllers/files.py:446 +#: kallithea/controllers/files.py:539 msgid "Unknown archive type" msgstr "未知包类型" -#: rhodecode/controllers/files.py:631 -#: rhodecode/templates/changeset/changeset_range.html:9 -#: rhodecode/templates/email_templates/pull_request.html:12 -#: rhodecode/templates/pullrequests/pullrequest.html:124 +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 msgid "Changesets" msgstr "修订集" -#: rhodecode/controllers/files.py:632 -#: rhodecode/controllers/pullrequests.py:149 -#: rhodecode/controllers/summary.py:76 rhodecode/model/scm.py:682 -#: rhodecode/templates/switch_to_list.html:3 -#: rhodecode/templates/branches/branches.html:10 +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 msgid "Branches" msgstr "分支" -#: rhodecode/controllers/files.py:633 -#: rhodecode/controllers/pullrequests.py:150 -#: rhodecode/controllers/summary.py:77 rhodecode/model/scm.py:693 -#: rhodecode/templates/switch_to_list.html:15 -#: rhodecode/templates/tags/tags.html:10 +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 msgid "Tags" msgstr "标签" -#: rhodecode/controllers/forks.py:176 -#, python-format -msgid "Forked repository %s as %s" -msgstr "" - -#: rhodecode/controllers/forks.py:190 +#: kallithea/controllers/forks.py:191 #, python-format msgid "An error occurred during repository forking %s" msgstr "在复刻版本库%s的时候发生错误" -#: rhodecode/controllers/journal.py:110 rhodecode/controllers/journal.py:153 +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "版本库" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 msgid "public journal" msgstr "公共日志" -#: rhodecode/controllers/journal.py:114 rhodecode/controllers/journal.py:157 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 msgid "journal" msgstr "日志" -#: rhodecode/controllers/login.py:138 -msgid "You have successfully registered into RhodeCode" -msgstr "" - -#: rhodecode/controllers/login.py:159 +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" +msgstr "" + +#: kallithea/controllers/login.py:237 msgid "Your password reset link was sent" msgstr "密码重置链接已经发送" -#: rhodecode/controllers/login.py:179 +#: kallithea/controllers/login.py:257 msgid "" -"Your password reset was successful, new password has been sent to your email" +"Your password reset was successful, new password has been sent to your " +"email" msgstr "密码已经成功重置,新密码已经发送到你的邮箱" -#: rhodecode/controllers/pullrequests.py:136 -#: rhodecode/templates/changeset/changeset.html:10 -#: rhodecode/templates/email_templates/changeset_comment.html:8 +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 msgid "Changeset" msgstr "修订集" -#: rhodecode/controllers/pullrequests.py:146 +#: kallithea/controllers/pullrequests.py:157 msgid "Special" msgstr "" -#: rhodecode/controllers/pullrequests.py:147 +#: kallithea/controllers/pullrequests.py:158 msgid "Peer branches" msgstr "" -#: rhodecode/controllers/pullrequests.py:148 rhodecode/model/scm.py:688 -#: rhodecode/templates/switch_to_list.html:28 -#: rhodecode/templates/bookmarks/bookmarks.html:10 +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 msgid "Bookmarks" msgstr "书签" -#: rhodecode/controllers/pullrequests.py:321 +#: kallithea/controllers/pullrequests.py:330 msgid "Pull request requires a title with min. 3 chars" msgstr "拉取请求的标题至少3个字符" -#: rhodecode/controllers/pullrequests.py:323 -msgid "Error creating pull request" -msgstr "" - -#: rhodecode/controllers/pullrequests.py:343 +#: kallithea/controllers/pullrequests.py:332 +#, python-format +msgid "Error creating pull request: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:354 msgid "Successfully opened new pull request" msgstr "成功提交拉取请求" -#: rhodecode/controllers/pullrequests.py:346 +#: kallithea/controllers/pullrequests.py:357 msgid "Error occurred during sending pull request" msgstr "提交拉取请求时发生错误" -#: rhodecode/controllers/pullrequests.py:385 +#: kallithea/controllers/pullrequests.py:397 msgid "Successfully deleted pull request" msgstr "成功删除拉取请求" -#: rhodecode/controllers/pullrequests.py:481 +#: kallithea/controllers/pullrequests.py:485 msgid "Closing with" msgstr "" -#: rhodecode/controllers/pullrequests.py:518 -msgid "" -"Closing pull request on other statuses than rejected or approved forbidden" +#: kallithea/controllers/pullrequests.py:522 +msgid "Closing pull request on other statuses than rejected or approved forbidden" msgstr "只能以批准或者驳回的状态关闭拉取请求" -#: rhodecode/controllers/search.py:132 +#: kallithea/controllers/search.py:135 msgid "Invalid search query. Try quoting it." msgstr "错误的搜索。请尝试用引号包含它。" -#: rhodecode/controllers/search.py:137 +#: kallithea/controllers/search.py:140 msgid "There is no index to search in. Please run whoosh indexer" msgstr "没有索引用于搜索。请运行whoosh索引器" -#: rhodecode/controllers/search.py:141 +#: kallithea/controllers/search.py:144 msgid "An error occurred during this search operation" msgstr "在搜索操作中发生异常" -#: rhodecode/controllers/summary.py:182 +#: kallithea/controllers/summary.py:203 msgid "No data loaded yet" msgstr "数据未加载" -#: rhodecode/controllers/summary.py:188 -#: rhodecode/templates/summary/summary.html:149 +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 msgid "Statistics are disabled for this repository" msgstr "该版本库统计功能已经禁用" -#: rhodecode/controllers/admin/defaults.py:96 +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:97 msgid "Default settings updated successfully" msgstr "默认设置已经成功更新" -#: rhodecode/controllers/admin/defaults.py:110 +#: kallithea/controllers/admin/defaults.py:111 msgid "Error occurred during update of defaults" msgstr "" -#: rhodecode/controllers/admin/gists.py:56 +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 msgid "forever" msgstr "" -#: rhodecode/controllers/admin/gists.py:57 +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 msgid "5 minutes" msgstr "" -#: rhodecode/controllers/admin/gists.py:58 +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 msgid "1 hour" msgstr "" -#: rhodecode/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 msgid "1 day" msgstr "" -#: rhodecode/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 msgid "1 month" msgstr "" -#: rhodecode/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 msgid "Lifetime" msgstr "" -#: rhodecode/controllers/admin/gists.py:127 +#: kallithea/controllers/admin/gists.py:147 msgid "Error occurred during gist creation" msgstr "" -#: rhodecode/controllers/admin/gists.py:165 +#: kallithea/controllers/admin/gists.py:185 #, python-format msgid "Deleted gist %s" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:50 -msgid "BASE" -msgstr "BASE" - -#: rhodecode/controllers/admin/ldap_settings.py:51 -msgid "ONELEVEL" -msgstr "ONELEVEL" - -#: rhodecode/controllers/admin/ldap_settings.py:52 -msgid "SUBTREE" -msgstr "SUBTREE" - -#: rhodecode/controllers/admin/ldap_settings.py:56 -msgid "NEVER" -msgstr "NEVER" - -#: rhodecode/controllers/admin/ldap_settings.py:57 -msgid "ALLOW" -msgstr "ALLOW" - -#: rhodecode/controllers/admin/ldap_settings.py:58 -msgid "TRY" -msgstr "TRY" - -#: rhodecode/controllers/admin/ldap_settings.py:59 -msgid "DEMAND" -msgstr "DEMAND" - -#: rhodecode/controllers/admin/ldap_settings.py:60 -msgid "HARD" -msgstr "HARD" - -#: rhodecode/controllers/admin/ldap_settings.py:64 -msgid "No encryption" -msgstr "未加密" - -#: rhodecode/controllers/admin/ldap_settings.py:65 -msgid "LDAPS connection" -msgstr "LDAPS连接" - -#: rhodecode/controllers/admin/ldap_settings.py:66 -msgid "START_TLS on LDAP connection" -msgstr "LDAP连接上的START_TLS" - -#: rhodecode/controllers/admin/ldap_settings.py:124 -msgid "LDAP settings updated successfully" -msgstr "LDAP设置已经成功更新" - -#: rhodecode/controllers/admin/ldap_settings.py:128 -msgid "Unable to activate ldap. The \"python-ldap\" library is missing." -msgstr "无法启用LDAP。缺失“python-ldap”库。" - -#: rhodecode/controllers/admin/ldap_settings.py:145 -msgid "Error occurred during update of ldap settings" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:58 -#: rhodecode/controllers/admin/permissions.py:62 -#: rhodecode/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "由于是系统帐号,无法编辑该用户" + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "你的帐号已经更新完成" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "已为用户添加电子邮件 %s" + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "保存电子邮件时发生错误" + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "成功删除用户电子邮件" + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 msgid "None" msgstr "无" -#: rhodecode/controllers/admin/permissions.py:59 -#: rhodecode/controllers/admin/permissions.py:63 -#: rhodecode/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 msgid "Read" msgstr "读" -#: rhodecode/controllers/admin/permissions.py:60 -#: rhodecode/controllers/admin/permissions.py:64 -#: rhodecode/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 msgid "Write" msgstr "写" -#: rhodecode/controllers/admin/permissions.py:61 -#: rhodecode/controllers/admin/permissions.py:65 -#: rhodecode/controllers/admin/permissions.py:69 -#: rhodecode/templates/admin/defaults/defaults.html:9 -#: rhodecode/templates/admin/ldap/ldap.html:9 -#: rhodecode/templates/admin/permissions/permissions.html:9 -#: rhodecode/templates/admin/repos/repo_add.html:10 -#: rhodecode/templates/admin/repos/repo_add.html:14 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:13 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:9 -#: rhodecode/templates/admin/users/user_add.html:8 -#: rhodecode/templates/admin/users/user_edit.html:9 -#: rhodecode/templates/admin/users/user_edit.html:133 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/admin/users/users.html:85 -#: rhodecode/templates/admin/users_groups/users_group_add.html:8 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 -#: rhodecode/templates/admin/users_groups/users_groups.html:9 -#: rhodecode/templates/base/base.html:317 -#: rhodecode/templates/base/base.html:318 -#: rhodecode/templates/base/base.html:324 -#: rhodecode/templates/base/base.html:325 +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 msgid "Admin" msgstr "管理" -#: rhodecode/controllers/admin/permissions.py:72 -#: rhodecode/controllers/admin/permissions.py:83 -#: rhodecode/controllers/admin/permissions.py:86 -#: rhodecode/controllers/admin/permissions.py:89 -#: rhodecode/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 msgid "Disabled" msgstr "停用" -#: rhodecode/controllers/admin/permissions.py:74 +#: kallithea/controllers/admin/permissions.py:78 msgid "Allowed with manual account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:80 msgid "Allowed with automatic account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:79 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1439 rhodecode/model/db.py:1444 +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 msgid "Manual activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:80 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1440 rhodecode/model/db.py:1445 +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 msgid "Automatic activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:84 -#: rhodecode/controllers/admin/permissions.py:87 -#: rhodecode/controllers/admin/permissions.py:90 -#: rhodecode/controllers/admin/permissions.py:93 +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 msgid "Enabled" msgstr "启用" -#: rhodecode/controllers/admin/permissions.py:138 -msgid "Default permissions updated successfully" -msgstr "成功更新默认权限" - -#: rhodecode/controllers/admin/permissions.py:152 +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:139 msgid "Error occurred during update of permissions" msgstr "" -#: rhodecode/controllers/admin/repos.py:128 -msgid "--REMOVE FORK--" -msgstr "-- 移除复刻 --" - -#: rhodecode/controllers/admin/repos.py:168 +#: kallithea/controllers/admin/repo_groups.py:186 +#, python-format +msgid "Created repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:198 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:256 +#, python-format +msgid "Updated repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:271 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:289 +#, python-format +msgid "This group contains %s repositores and cannot be deleted" +msgstr "这个组内有%s个版本库因而无法删除" + +#: kallithea/controllers/admin/repo_groups.py:296 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:302 +#, python-format +msgid "Removed repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:237 #, python-format msgid "Created repository %s from %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:174 +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:249 #, python-format msgid "Created repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:197 -#, python-format -msgid "Error creating repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:270 +#: kallithea/controllers/admin/repos.py:289 #, python-format msgid "Repository %s updated successfully" msgstr "版本库%s成功更新" -#: rhodecode/controllers/admin/repos.py:288 +#: kallithea/controllers/admin/repos.py:307 #, python-format msgid "Error occurred during update of repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:315 +#: kallithea/controllers/admin/repos.py:334 #, python-format msgid "Detached %s forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:318 +#: kallithea/controllers/admin/repos.py:337 #, python-format msgid "Deleted %s forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:323 +#: kallithea/controllers/admin/repos.py:342 #, python-format msgid "Deleted repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:326 +#: kallithea/controllers/admin/repos.py:345 #, python-format msgid "Cannot delete %s it still contains attached forks" msgstr "无法删除%s因为它还有其他分复刻本库" -#: rhodecode/controllers/admin/repos.py:331 +#: kallithea/controllers/admin/repos.py:350 #, python-format msgid "An error occurred during deletion of %s" msgstr "在删除%s的时候发生错误" -#: rhodecode/controllers/admin/repos.py:345 +#: kallithea/controllers/admin/repos.py:402 msgid "Repository permissions updated" msgstr "" -#: rhodecode/controllers/admin/repos.py:375 -#: rhodecode/controllers/admin/repos_groups.py:332 -#: rhodecode/controllers/admin/users_groups.py:312 -msgid "An error occurred during revoking of permission" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:392 -msgid "An error occurred during deletion of repository stats" -msgstr "删除版本库统计时发生错误" - -#: rhodecode/controllers/admin/repos.py:409 -msgid "An error occurred during cache invalidation" -msgstr "清除缓存时发生错误" - -#: rhodecode/controllers/admin/repos.py:429 -#: rhodecode/controllers/admin/repos.py:456 -msgid "An error occurred during unlocking" -msgstr "解锁时发生错误" - -#: rhodecode/controllers/admin/repos.py:447 -msgid "Unlocked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:450 -msgid "Locked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:452 -#, python-format -msgid "Repository has been %s" -msgstr "版本库已被%s" - -#: rhodecode/controllers/admin/repos.py:476 +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "" + +#: kallithea/controllers/admin/repos.py:522 msgid "Updated repository visibility in public journal" msgstr "成功更新在公共日志中的可见性" -#: rhodecode/controllers/admin/repos.py:480 +#: kallithea/controllers/admin/repos.py:526 msgid "An error occurred during setting this repository in public journal" msgstr "设置版本库到公共日志时发生错误" -#: rhodecode/controllers/admin/repos.py:485 rhodecode/model/validators.py:302 +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 msgid "Token mismatch" msgstr "令牌不匹配" -#: rhodecode/controllers/admin/repos.py:498 -msgid "Pulled from remote location" -msgstr "成功拉取自远程路径" - -#: rhodecode/controllers/admin/repos.py:501 -msgid "An error occurred during pull from remote location" -msgstr "从远程路径拉取时发生错误" - -#: rhodecode/controllers/admin/repos.py:517 +#: kallithea/controllers/admin/repos.py:546 msgid "Nothing" msgstr "无" -#: rhodecode/controllers/admin/repos.py:519 +#: kallithea/controllers/admin/repos.py:548 #, python-format msgid "Marked repo %s as fork of %s" msgstr "成功将版本库%s标记为复刻自%s" -#: rhodecode/controllers/admin/repos.py:523 +#: kallithea/controllers/admin/repos.py:555 msgid "An error occurred during this operation" msgstr "在搜索操作中发生错误" -#: rhodecode/controllers/admin/repos.py:562 -msgid "An error occurred during creation of field" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:576 -msgid "An error occurred during removal of field" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:147 -#, python-format -msgid "Created repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:159 -#, python-format -msgid "Error occurred during creation of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:217 -#, python-format -msgid "Updated repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:232 -#, python-format -msgid "Error occurred during update of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:250 -#, python-format -msgid "This group contains %s repositores and cannot be deleted" -msgstr "这个组内有%s个版本库因而无法删除" - -#: rhodecode/controllers/admin/repos_groups.py:257 -#, python-format -msgid "This group contains %s subgroups and cannot be deleted" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:263 -#, python-format -msgid "Removed repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:268 -#, python-format -msgid "Error occurred during deletion of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:279 -#: rhodecode/controllers/admin/repos_groups.py:314 -#: rhodecode/controllers/admin/users_groups.py:300 -msgid "Cannot revoke permission for yourself as admin" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:294 -msgid "Repository Group permissions updated" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:123 +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 +msgid "An error occurred during unlocking" +msgstr "解锁时发生错误" + +#: kallithea/controllers/admin/repos.py:595 +msgid "Unlocked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:598 +msgid "Locked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:600 +#, python-format +msgid "Repository has been %s" +msgstr "版本库已被%s" + +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "清除缓存时发生错误" + +#: kallithea/controllers/admin/repos.py:637 +msgid "Pulled from remote location" +msgstr "成功拉取自远程路径" + +#: kallithea/controllers/admin/repos.py:640 +msgid "An error occurred during pull from remote location" +msgstr "从远程路径拉取时发生错误" + +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "删除版本库统计时发生错误" + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "成功更新版本控制系统设置" + +#: kallithea/controllers/admin/settings.py:176 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:215 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" msgstr "" -#: rhodecode/controllers/admin/settings.py:132 -msgid "Whoosh reindex task scheduled" -msgstr "Whoosh重新索引任务调度" - -#: rhodecode/controllers/admin/settings.py:163 +#: kallithea/controllers/admin/settings.py:270 msgid "Updated application settings" msgstr "更新应用设置" -#: rhodecode/controllers/admin/settings.py:167 -#: rhodecode/controllers/admin/settings.py:304 -msgid "Error occurred during updating application settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:219 +#: kallithea/controllers/admin/settings.py:327 msgid "Updated visualisation settings" msgstr "成功更新可视化设置" -#: rhodecode/controllers/admin/settings.py:224 +#: kallithea/controllers/admin/settings.py:332 msgid "Error occurred during updating visualisation settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:300 -msgid "Updated VCS settings" -msgstr "成功更新版本控制系统设置" - -#: rhodecode/controllers/admin/settings.py:314 +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "" + +#: kallithea/controllers/admin/settings.py:400 msgid "Added new hook" msgstr "新建钩子" -#: rhodecode/controllers/admin/settings.py:326 +#: kallithea/controllers/admin/settings.py:414 msgid "Updated hooks" msgstr "更新钩子" -#: rhodecode/controllers/admin/settings.py:330 +#: kallithea/controllers/admin/settings.py:418 msgid "Error occurred during hook creation" msgstr "" -#: rhodecode/controllers/admin/settings.py:349 -msgid "Email task created" -msgstr "已创建电子邮件任务" - -#: rhodecode/controllers/admin/settings.py:413 -msgid "You can't edit this user since it's crucial for entire application" -msgstr "由于是系统帐号,无法编辑该用户" - -#: rhodecode/controllers/admin/settings.py:455 -msgid "Your account was updated successfully" -msgstr "你的帐号已经更新完成" - -#: rhodecode/controllers/admin/settings.py:470 -#: rhodecode/controllers/admin/users.py:198 -#, python-format -msgid "Error occurred during update of user %s" -msgstr "" - -#: rhodecode/controllers/admin/users.py:130 +#: kallithea/controllers/admin/settings.py:444 +msgid "Whoosh reindex task scheduled" +msgstr "Whoosh重新索引任务调度" + +#: kallithea/controllers/admin/user_groups.py:150 +#, python-format +msgid "Created user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:161 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Updated user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:221 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:239 +msgid "Successfully deleted user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:244 +msgid "An error occurred during deletion of user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:311 +msgid "Target group cannot be the same" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:317 +msgid "User Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "保存权限时发生错误" + +#: kallithea/controllers/admin/users.py:135 #, python-format msgid "Created user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:142 +#: kallithea/controllers/admin/users.py:149 #, python-format msgid "Error occurred during creation of user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:176 +#: kallithea/controllers/admin/users.py:188 msgid "User updated successfully" msgstr "用户更新成功" -#: rhodecode/controllers/admin/users.py:214 +#: kallithea/controllers/admin/users.py:223 msgid "Successfully deleted user" msgstr "" -#: rhodecode/controllers/admin/users.py:219 +#: kallithea/controllers/admin/users.py:228 msgid "An error occurred during deletion of user" msgstr "删除用户时发生错误" -#: rhodecode/controllers/admin/users.py:234 +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 msgid "You can't edit this user" msgstr "无法编辑该用户" -#: rhodecode/controllers/admin/users.py:293 -#: rhodecode/controllers/admin/users_groups.py:372 -msgid "Updated permissions" -msgstr "" - -#: rhodecode/controllers/admin/users.py:297 -#: rhodecode/controllers/admin/users_groups.py:376 -msgid "An error occurred during permissions saving" -msgstr "保存权限时发生错误" - -#: rhodecode/controllers/admin/users.py:311 -#, python-format -msgid "Added email %s to user" -msgstr "已为用户添加电子邮件 %s" - -#: rhodecode/controllers/admin/users.py:317 -msgid "An error occurred during email saving" -msgstr "保存电子邮件时发生错误" - -#: rhodecode/controllers/admin/users.py:327 -msgid "Removed email from user" -msgstr "成功删除用户电子邮件" - -#: rhodecode/controllers/admin/users.py:340 -#, python-format -msgid "Added ip %s to user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:346 +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "" + +#: kallithea/controllers/admin/users.py:489 msgid "An error occurred during ip saving" msgstr "" -#: rhodecode/controllers/admin/users.py:358 -msgid "Removed ip from user" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:162 -#, python-format -msgid "Created user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:173 -#, python-format -msgid "Error occurred during creation of user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:210 -#, python-format -msgid "Updated user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:232 -#, python-format -msgid "Error occurred during update of user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:250 -msgid "Successfully deleted user group" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:255 -msgid "An error occurred during deletion of user group" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:274 -msgid "Target group cannot be the same" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:280 -msgid "User Group permissions updated" -msgstr "" - -#: rhodecode/lib/auth.py:544 +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "" + +#: kallithea/lib/auth.py:748 #, python-format msgid "IP %s not allowed" msgstr "" -#: rhodecode/lib/auth.py:593 +#: kallithea/lib/auth.py:809 msgid "You need to be a registered user to perform this action" msgstr "必须是注册用户才能进行此操作" -#: rhodecode/lib/auth.py:634 +#: kallithea/lib/auth.py:846 msgid "You need to be a signed in to view this page" msgstr "必须登录才能访问该页面" -#: rhodecode/lib/diffs.py:66 +#: kallithea/lib/diffs.py:66 msgid "Binary file" msgstr "" -#: rhodecode/lib/diffs.py:82 -msgid "" -"Changeset was too big and was cut off, use diff menu to display this diff" +#: kallithea/lib/diffs.py:82 +msgid "Changeset was too big and was cut off, use diff menu to display this diff" msgstr "修订集因过大而被截断,可查看原始修订集作为替代" -#: rhodecode/lib/diffs.py:92 +#: kallithea/lib/diffs.py:92 msgid "No changes detected" msgstr "未发现差异" -#: rhodecode/lib/helpers.py:539 -msgid "True" -msgstr "是" - -#: rhodecode/lib/helpers.py:542 -msgid "False" -msgstr "否" - -#: rhodecode/lib/helpers.py:580 +#: kallithea/lib/helpers.py:598 #, python-format msgid "Deleted branch: %s" msgstr "已经删除分支%s" -#: rhodecode/lib/helpers.py:583 +#: kallithea/lib/helpers.py:601 #, python-format msgid "Created tag: %s" msgstr "创建标签%s" -#: rhodecode/lib/helpers.py:596 +#: kallithea/lib/helpers.py:614 msgid "Changeset not found" msgstr "未找到修订集" -#: rhodecode/lib/helpers.py:646 +#: kallithea/lib/helpers.py:664 #, python-format msgid "Show all combined changesets %s->%s" msgstr "显示合并的修订集%s->%s" -#: rhodecode/lib/helpers.py:652 +#: kallithea/lib/helpers.py:670 msgid "compare view" msgstr "比较显示" -#: rhodecode/lib/helpers.py:672 +#: kallithea/lib/helpers.py:690 msgid "and" msgstr "还有" -#: rhodecode/lib/helpers.py:673 +#: kallithea/lib/helpers.py:691 #, python-format msgid "%s more" msgstr "%s个" -#: rhodecode/lib/helpers.py:674 -#: rhodecode/templates/changelog/changelog.html:53 +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 msgid "revisions" msgstr "修订" -#: rhodecode/lib/helpers.py:698 +#: kallithea/lib/helpers.py:716 #, python-format msgid "fork name %s" msgstr "复刻名称%s" -#: rhodecode/lib/helpers.py:715 -#: rhodecode/templates/pullrequests/pullrequest_show.html:8 +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 #, python-format msgid "Pull request #%s" msgstr "拉取请求#%s" -#: rhodecode/lib/helpers.py:725 +#: kallithea/lib/helpers.py:743 msgid "[deleted] repository" msgstr "[删除]版本库" -#: rhodecode/lib/helpers.py:727 rhodecode/lib/helpers.py:739 +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 msgid "[created] repository" msgstr "[创建]版本库" -#: rhodecode/lib/helpers.py:729 +#: kallithea/lib/helpers.py:747 msgid "[created] repository as fork" msgstr "[创建]复刻版本库" -#: rhodecode/lib/helpers.py:731 rhodecode/lib/helpers.py:741 +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 msgid "[forked] repository" msgstr "[复刻]版本库" -#: rhodecode/lib/helpers.py:733 rhodecode/lib/helpers.py:743 +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 msgid "[updated] repository" msgstr "[更新]版本库" -#: rhodecode/lib/helpers.py:735 +#: kallithea/lib/helpers.py:753 msgid "[downloaded] archive from repository" msgstr "" -#: rhodecode/lib/helpers.py:737 +#: kallithea/lib/helpers.py:755 msgid "[delete] repository" msgstr "[删除]版本库" -#: rhodecode/lib/helpers.py:745 +#: kallithea/lib/helpers.py:763 msgid "[created] user" msgstr "[创建]用户" -#: rhodecode/lib/helpers.py:747 +#: kallithea/lib/helpers.py:765 msgid "[updated] user" msgstr "[更新]用户" -#: rhodecode/lib/helpers.py:749 +#: kallithea/lib/helpers.py:767 msgid "[created] user group" msgstr "" -#: rhodecode/lib/helpers.py:751 +#: kallithea/lib/helpers.py:769 msgid "[updated] user group" msgstr "" -#: rhodecode/lib/helpers.py:753 +#: kallithea/lib/helpers.py:771 msgid "[commented] on revision in repository" msgstr "[评论]了版本库中的修订" -#: rhodecode/lib/helpers.py:755 +#: kallithea/lib/helpers.py:773 msgid "[commented] on pull request for" msgstr "[评论]拉取请求" -#: rhodecode/lib/helpers.py:757 +#: kallithea/lib/helpers.py:775 msgid "[closed] pull request for" msgstr "[关闭] 拉取请求" -#: rhodecode/lib/helpers.py:759 +#: kallithea/lib/helpers.py:777 msgid "[pushed] into" msgstr "[推送]到" -#: rhodecode/lib/helpers.py:761 -msgid "[committed via RhodeCode] into repository" -msgstr "[通过RhodeCode提交]到版本库" - -#: rhodecode/lib/helpers.py:763 +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "[通过Kallithea提交]到版本库" + +#: kallithea/lib/helpers.py:781 msgid "[pulled from remote] into repository" msgstr "[远程拉取]到版本库" -#: rhodecode/lib/helpers.py:765 +#: kallithea/lib/helpers.py:783 msgid "[pulled] from" msgstr "[拉取]自" -#: rhodecode/lib/helpers.py:767 +#: kallithea/lib/helpers.py:785 msgid "[started following] repository" msgstr "[开始关注]版本库" -#: rhodecode/lib/helpers.py:769 +#: kallithea/lib/helpers.py:787 msgid "[stopped following] repository" msgstr "[停止关注]版本库" -#: rhodecode/lib/helpers.py:1088 +#: kallithea/lib/helpers.py:1101 #, python-format msgid " and %s more" msgstr "还有%s个" -#: rhodecode/lib/helpers.py:1092 +#: kallithea/lib/helpers.py:1105 msgid "No Files" msgstr "没有文件" -#: rhodecode/lib/helpers.py:1158 +#: kallithea/lib/helpers.py:1171 msgid "new file" msgstr "" -#: rhodecode/lib/helpers.py:1161 +#: kallithea/lib/helpers.py:1174 msgid "mod" msgstr "" -#: rhodecode/lib/helpers.py:1164 +#: kallithea/lib/helpers.py:1177 msgid "del" msgstr "" -#: rhodecode/lib/helpers.py:1167 +#: kallithea/lib/helpers.py:1180 msgid "rename" msgstr "" -#: rhodecode/lib/helpers.py:1172 +#: kallithea/lib/helpers.py:1185 msgid "chmod" msgstr "" -#: rhodecode/lib/helpers.py:1404 +#: kallithea/lib/helpers.py:1417 #, python-format msgid "" -"%s repository is not mapped to db perhaps it was created or renamed from the" -" filesystem please run the application again in order to rescan repositories" -msgstr "版本库%s没有映射到数据库,可能是从文件系统创建或者重命名,请重启RhodeCode以重新扫描版本库" - -#: rhodecode/lib/unionrepo.py:193 -msgid "cannot create new union repository" -msgstr "" - -#: rhodecode/lib/utils2.py:410 +"%s repository is not mapped to db perhaps it was created or renamed from " +"the filesystem please run the application again in order to rescan " +"repositories" +msgstr "版本库%s没有映射到数据库,可能是从文件系统创建或者重命名,请重启Kallithea以重新扫描版本库" + +#: kallithea/lib/utils2.py:415 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d年" -#: rhodecode/lib/utils2.py:411 +#: kallithea/lib/utils2.py:416 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d月" -#: rhodecode/lib/utils2.py:412 +#: kallithea/lib/utils2.py:417 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d天" -#: rhodecode/lib/utils2.py:413 +#: kallithea/lib/utils2.py:418 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d时" -#: rhodecode/lib/utils2.py:414 +#: kallithea/lib/utils2.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d分" -#: rhodecode/lib/utils2.py:415 +#: kallithea/lib/utils2.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d秒" -#: rhodecode/lib/utils2.py:431 +#: kallithea/lib/utils2.py:436 #, python-format msgid "in %s" msgstr "%s" -#: rhodecode/lib/utils2.py:433 +#: kallithea/lib/utils2.py:438 #, python-format msgid "%s ago" msgstr "%s前" -#: rhodecode/lib/utils2.py:435 +#: kallithea/lib/utils2.py:440 #, python-format msgid "in %s and %s" msgstr "%s零%s" -#: rhodecode/lib/utils2.py:438 +#: kallithea/lib/utils2.py:443 #, python-format msgid "%s and %s ago" msgstr "%s零%s前" -#: rhodecode/lib/utils2.py:441 +#: kallithea/lib/utils2.py:446 msgid "just now" msgstr "刚才" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1163 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1303 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1388 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1408 rhodecode/model/db.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 msgid "Repository no access" msgstr "无版本库访问权限" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1164 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1184 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1304 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1389 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1409 rhodecode/model/db.py:1414 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 msgid "Repository read access" msgstr "版本库读取权限" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1165 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1185 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1305 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1390 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1410 rhodecode/model/db.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 msgid "Repository write access" msgstr "版本库写入权限" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1166 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1186 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1306 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1391 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1411 rhodecode/model/db.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 msgid "Repository admin access" msgstr "版本库管理权限" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1168 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 msgid "Repositories Group no access" msgstr "无版本库组访问权限" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1169 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1309 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 msgid "Repositories Group read access" msgstr "版本库组读取权限" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1170 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1310 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 msgid "Repositories Group write access" msgstr "版本库组写入" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1171 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1311 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 msgid "Repositories Group admin access" msgstr "版本库组管理权限" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1173 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1193 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1313 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1398 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1406 rhodecode/model/db.py:1411 -msgid "RhodeCode Administrator" -msgstr "RhodeCode 管理员" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1174 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1194 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1314 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1399 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1429 rhodecode/model/db.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" +msgstr "Kallithea 管理员" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 msgid "Repository creation disabled" msgstr "禁用创建版本库" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1175 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1195 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1315 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1400 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1430 rhodecode/model/db.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 msgid "Repository creation enabled" msgstr "允许创建版本库" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1176 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1196 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1316 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1401 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1432 rhodecode/model/db.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 msgid "Repository forking disabled" msgstr "禁用复刻版本库" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1177 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1197 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1317 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1402 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1433 rhodecode/model/db.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 msgid "Repository forking enabled" msgstr "允许复刻版本库" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1178 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1318 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 msgid "Register disabled" msgstr "禁用注册" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1319 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1404 -msgid "Register new user with RhodeCode with manual activation" +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" msgstr "用手动激活注册新用户" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1202 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1407 -msgid "Register new user with RhodeCode with auto activation" +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" msgstr "用自动激活注册新用户" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1623 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1643 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1763 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1838 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1934 rhodecode/model/db.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 msgid "Not Reviewed" msgstr "未检视" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1624 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1644 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1764 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1839 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1935 rhodecode/model/db.py:1940 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 msgid "Approved" msgstr "已批准" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1625 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1645 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1765 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1840 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1936 rhodecode/model/db.py:1941 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 msgid "Rejected" msgstr "驳回" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1626 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1646 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1766 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1841 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1937 rhodecode/model/db.py:1942 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 msgid "Under Review" msgstr "检视中" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1252 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1270 rhodecode/model/db.py:1275 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 msgid "top level" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1393 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1413 rhodecode/model/db.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 msgid "Repository group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1394 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1414 rhodecode/model/db.py:1419 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 msgid "Repository group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1395 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1415 rhodecode/model/db.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 msgid "Repository group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1396 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1416 rhodecode/model/db.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 msgid "Repository group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1418 rhodecode/model/db.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 msgid "User group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1419 rhodecode/model/db.py:1424 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 msgid "User group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1420 rhodecode/model/db.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 msgid "User group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1421 rhodecode/model/db.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 msgid "User group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1423 rhodecode/model/db.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 msgid "Repository Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1424 rhodecode/model/db.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 msgid "Repository Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1426 rhodecode/model/db.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 msgid "User Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1427 rhodecode/model/db.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 msgid "User Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1435 rhodecode/model/db.py:1440 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 msgid "Registration disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1436 rhodecode/model/db.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 msgid "User Registration with manual account activation" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1437 rhodecode/model/db.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 msgid "User Registration with automatic account activation" msgstr "" -#: rhodecode/model/comment.py:75 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:77 #, python-format msgid "on line %s" msgstr "在%s行" -#: rhodecode/model/comment.py:220 +#: kallithea/model/comment.py:222 msgid "[Mention]" msgstr "[提及]" -#: rhodecode/model/forms.py:43 +#: kallithea/model/forms.py:57 msgid "Please enter a login" msgstr "请登录" -#: rhodecode/model/forms.py:44 +#: kallithea/model/forms.py:58 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "输入一个不少于%(min)i个字符的值" -#: rhodecode/model/forms.py:52 +#: kallithea/model/forms.py:66 msgid "Please enter a password" msgstr "请输入密码" -#: rhodecode/model/forms.py:53 +#: kallithea/model/forms.py:67 #, python-format msgid "Enter %(min)i characters or more" msgstr "输入少于%(min)i个字符" -#: rhodecode/model/notification.py:228 +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:231 #, python-format msgid "%(user)s commented on changeset at %(when)s" msgstr "" -#: rhodecode/model/notification.py:229 +#: kallithea/model/notification.py:232 #, python-format msgid "%(user)s sent message at %(when)s" msgstr "" -#: rhodecode/model/notification.py:230 +#: kallithea/model/notification.py:233 #, python-format msgid "%(user)s mentioned you at %(when)s" msgstr "" -#: rhodecode/model/notification.py:231 -#, python-format -msgid "%(user)s registered in RhodeCode at %(when)s" -msgstr "" - -#: rhodecode/model/notification.py:232 +#: kallithea/model/notification.py:234 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:235 #, python-format msgid "%(user)s opened new pull request at %(when)s" msgstr "" -#: rhodecode/model/notification.py:233 +#: kallithea/model/notification.py:236 #, python-format msgid "%(user)s commented on pull request at %(when)s" msgstr "" -#: rhodecode/model/pull_request.py:98 +#: kallithea/model/pull_request.py:107 #, python-format msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" msgstr "" -#: rhodecode/model/scm.py:674 +#: kallithea/model/scm.py:810 msgid "latest tip" msgstr "最新tip版本" -#: rhodecode/model/user.py:232 +#: kallithea/model/user.py:198 msgid "New user registration" msgstr "" -#: rhodecode/model/user.py:257 rhodecode/model/user.py:281 +#: kallithea/model/user.py:222 kallithea/model/user.py:247 msgid "You can't Edit this user since it's crucial for entire application" msgstr "由于是系统帐号,无法编辑该用户" -#: rhodecode/model/user.py:303 +#: kallithea/model/user.py:270 msgid "You can't remove this user since it's crucial for entire application" msgstr "由于是系统帐号,无法删除该用户" -#: rhodecode/model/user.py:309 +#: kallithea/model/user.py:276 #, python-format msgid "" -"user \"%s\" still owns %s repositories and cannot be removed. Switch owners " -"or remove those repositories. %s" +"user \"%s\" still owns %s repositories and cannot be removed. Switch " +"owners or remove those repositories. %s" msgstr "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本库。%s" -#: rhodecode/model/user.py:334 +#: kallithea/model/user.py:304 msgid "Password reset link" msgstr "" -#: rhodecode/model/user.py:366 +#: kallithea/model/user.py:333 msgid "Your new password" msgstr "" -#: rhodecode/model/user.py:367 -#, python-format -msgid "Your new RhodeCode password:%s" -msgstr "" - -#: rhodecode/model/validators.py:38 rhodecode/model/validators.py:39 +#: kallithea/model/user.py:334 +#, python-format +msgid "Your new Kallithea password:%s" +msgstr "" + +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 msgid "Value cannot be an empty list" msgstr "值不能为空" -#: rhodecode/model/validators.py:85 +#: kallithea/model/validators.py:120 #, python-format msgid "Username \"%(username)s\" already exists" msgstr "用户名称%(username)s已经存在" -#: rhodecode/model/validators.py:87 +#: kallithea/model/validators.py:122 #, python-format msgid "Username \"%(username)s\" is forbidden" msgstr "不允许用户名 \"%(username)s\"" -#: rhodecode/model/validators.py:89 +#: kallithea/model/validators.py:124 msgid "" -"Username may only contain alphanumeric characters underscores, periods or " -"dashes and must begin with alphanumeric character or underscore" -msgstr "" - -#: rhodecode/model/validators.py:117 +"Username may only contain alphanumeric characters underscores, periods or" +" dashes and must begin with alphanumeric character or underscore" +msgstr "" + +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:158 #, python-format msgid "Username %(username)s is not valid" msgstr "用户名称 %(username)s 无效" -#: rhodecode/model/validators.py:136 +#: kallithea/model/validators.py:177 msgid "Invalid user group name" msgstr "" -#: rhodecode/model/validators.py:137 +#: kallithea/model/validators.py:178 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:139 +#: kallithea/model/validators.py:180 msgid "" "user group name may only contain alphanumeric characters underscores, " "periods or dashes and must begin with alphanumeric character" msgstr "" -#: rhodecode/model/validators.py:177 +#: kallithea/model/validators.py:218 msgid "Cannot assign this group as parent" msgstr "不能将这个组作为parent" -#: rhodecode/model/validators.py:178 +#: kallithea/model/validators.py:219 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "组 \"%(group_name)s\" 已经存在" -#: rhodecode/model/validators.py:180 +#: kallithea/model/validators.py:221 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "已经存在名为 \"%(group_name)s\" 的版本库" -#: rhodecode/model/validators.py:238 +#: kallithea/model/validators.py:279 msgid "Invalid characters (non-ascii) in password" msgstr "密码含有无效(非ASCII)字符" -#: rhodecode/model/validators.py:253 +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 msgid "Passwords do not match" msgstr "密码不符" -#: rhodecode/model/validators.py:270 +#: kallithea/model/validators.py:327 msgid "invalid password" msgstr "无效密码" -#: rhodecode/model/validators.py:271 +#: kallithea/model/validators.py:328 msgid "invalid user name" msgstr "无效用户名" -#: rhodecode/model/validators.py:272 +#: kallithea/model/validators.py:329 msgid "Your account is disabled" msgstr "该帐号已被禁用" -#: rhodecode/model/validators.py:316 +#: kallithea/model/validators.py:373 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "版本库名称不能为%(repo)s" -#: rhodecode/model/validators.py:318 +#: kallithea/model/validators.py:375 #, python-format msgid "Repository named %(repo)s already exists" msgstr "已经存在版本库%(repo)s" -#: rhodecode/model/validators.py:319 +#: kallithea/model/validators.py:376 #, python-format msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" msgstr "版本库组 \"%(group)s\" 中已经存在版本库 \"%(repo)s\"" -#: rhodecode/model/validators.py:321 +#: kallithea/model/validators.py:378 #, python-format msgid "Repository group with name \"%(repo)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:438 +#: kallithea/model/validators.py:493 msgid "invalid clone url" msgstr "无效的克隆地址" -#: rhodecode/model/validators.py:439 +#: kallithea/model/validators.py:494 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" msgstr "无效的克隆地址,提供一个有效的克隆 http(s)或svn+http(s)地址" -#: rhodecode/model/validators.py:464 +#: kallithea/model/validators.py:519 msgid "Fork have to be the same type as parent" msgstr "复刻版本库必须和父版本库类型相同" -#: rhodecode/model/validators.py:479 +#: kallithea/model/validators.py:534 msgid "You don't have permissions to create repository in this group" msgstr "没有在该版本库组中创建版本库的权限" -#: rhodecode/model/validators.py:481 +#: kallithea/model/validators.py:536 msgid "no permission to create repository in root location" msgstr "" -#: rhodecode/model/validators.py:518 +#: kallithea/model/validators.py:585 msgid "You don't have permissions to create a group in this location" msgstr "" -#: rhodecode/model/validators.py:559 +#: kallithea/model/validators.py:626 msgid "This username or user group name is not valid" msgstr "" -#: rhodecode/model/validators.py:652 +#: kallithea/model/validators.py:719 msgid "This is not a valid path" msgstr "不是一个合法的路径" -#: rhodecode/model/validators.py:667 +#: kallithea/model/validators.py:734 msgid "This e-mail address is already taken" msgstr "该邮件地址已被使用" -#: rhodecode/model/validators.py:687 +#: kallithea/model/validators.py:754 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "邮件地址\"%(email)s\"不存在" -#: rhodecode/model/validators.py:724 +#: kallithea/model/validators.py:791 msgid "" -"The LDAP Login attribute of the CN must be specified - this is the name of " -"the attribute that is equivalent to \"username\"" +"The LDAP Login attribute of the CN must be specified - this is the name " +"of the attribute that is equivalent to \"username\"" msgstr "LDAP 登陆属性的 CN 必须指定 - 这个名字作为用户名" -#: rhodecode/model/validators.py:737 +#: kallithea/model/validators.py:804 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" msgstr "修订%(revs)s已经包含在拉取请求中或者或者已经设置状态" -#: rhodecode/model/validators.py:769 +#: kallithea/model/validators.py:836 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "" -#: rhodecode/model/validators.py:770 -#, python-format -msgid "" -"The network size (bits) must be within the range of 0-32 (not %(bits)r)" -msgstr "" - -#: rhodecode/model/validators.py:803 +#: kallithea/model/validators.py:837 +#, python-format +msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" +msgstr "" + +#: kallithea/model/validators.py:870 msgid "Key name can only consist of letters, underscore, dash or numbers" msgstr "" -#: rhodecode/model/validators.py:817 +#: kallithea/model/validators.py:884 msgid "Filename cannot be inside a directory" msgstr "" -#: rhodecode/templates/index.html:5 +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" +msgstr "" + +#: kallithea/templates/index.html:5 msgid "Dashboard" msgstr "控制面板" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/repo_switcher_list.html:4 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/users/user_edit_my_account.html:31 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/bookmarks/bookmarks.html:9 -#: rhodecode/templates/branches/branches.html:9 -#: rhodecode/templates/journal/journal.html:9 -#: rhodecode/templates/journal/journal.html:46 -#: rhodecode/templates/journal/journal.html:47 -#: rhodecode/templates/tags/tags.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 msgid "quick filter..." msgstr "快速过滤..." -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/admin/repos/repos.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 msgid "repositories" msgstr "版本库" -#: rhodecode/templates/index_base.html:13 -#: rhodecode/templates/index_base.html:18 -#: rhodecode/templates/admin/repos/repo_add.html:5 -#: rhodecode/templates/admin/repos/repos.html:22 -msgid "Add repository" -msgstr "添加版本库" - -#: rhodecode/templates/index_base.html:15 -#: rhodecode/templates/index_base.html:20 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:31 -msgid "Add group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 -msgid "Edit group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" +msgstr "" + +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:32 msgid "You have admin right to this group, and can edit it" msgstr "" -#: rhodecode/templates/index_base.html:40 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:33 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:38 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:43 -#: rhodecode/templates/admin/users_groups/users_group_add.html:32 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 -#: rhodecode/templates/admin/users_groups/users_groups.html:37 -msgid "Group name" -msgstr "组名" - -#: rhodecode/templates/index_base.html:41 -#: rhodecode/templates/index_base.html:123 -#: rhodecode/templates/admin/repos/repo_add_base.html:56 -#: rhodecode/templates/admin/repos/repo_edit.html:68 -#: rhodecode/templates/admin/repos/repos.html:75 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:42 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:47 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:44 -#: rhodecode/templates/email_templates/changeset_comment.html:9 -#: rhodecode/templates/email_templates/pull_request.html:9 -#: rhodecode/templates/forks/fork.html:56 -#: rhodecode/templates/pullrequests/pullrequest.html:43 -#: rhodecode/templates/pullrequests/pullrequest_show.html:81 -#: rhodecode/templates/summary/summary.html:106 +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" +msgstr "" + +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 msgid "Description" msgstr "描述" -#: rhodecode/templates/index_base.html:51 -#: rhodecode/templates/admin/permissions/permissions.html:55 -#: rhodecode/templates/admin/repos/repo_add_base.html:29 -#: rhodecode/templates/admin/repos/repo_edit.html:50 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:57 -#: rhodecode/templates/forks/fork.html:47 -msgid "Repository group" -msgstr "版本库组" - -#: rhodecode/templates/index_base.html:121 -#: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit.html:32 -#: rhodecode/templates/admin/repos/repos.html:73 -#: rhodecode/templates/admin/users/user_edit_my_account.html:172 -#: rhodecode/templates/base/perms_summary.html:37 -#: rhodecode/templates/bookmarks/bookmarks.html:48 -#: rhodecode/templates/bookmarks/bookmarks_data.html:6 -#: rhodecode/templates/branches/branches.html:47 -#: rhodecode/templates/branches/branches_data.html:6 -#: rhodecode/templates/files/files_browser.html:47 -#: rhodecode/templates/journal/journal.html:193 -#: rhodecode/templates/journal/journal.html:283 -#: rhodecode/templates/summary/summary.html:55 -#: rhodecode/templates/summary/summary.html:124 -#: rhodecode/templates/tags/tags.html:48 -#: rhodecode/templates/tags/tags_data.html:6 +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 msgid "Name" msgstr "名称" -#: rhodecode/templates/index_base.html:124 +#: kallithea/templates/index_base.html:129 msgid "Last Change" msgstr "最后修改" -#: rhodecode/templates/index_base.html:126 -#: rhodecode/templates/admin/repos/repos.html:76 -#: rhodecode/templates/admin/users/user_edit_my_account.html:174 -#: rhodecode/templates/journal/journal.html:195 -#: rhodecode/templates/journal/journal.html:285 +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 msgid "Tip" msgstr "Tip" -#: rhodecode/templates/index_base.html:128 -#: rhodecode/templates/admin/repos/repo_edit.html:114 -#: rhodecode/templates/admin/repos/repos.html:78 +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 msgid "Owner" msgstr "所有者" -#: rhodecode/templates/index_base.html:136 -#: rhodecode/templates/admin/repos/repos.html:86 -#: rhodecode/templates/admin/users/user_edit_my_account.html:183 -#: rhodecode/templates/admin/users/users.html:107 -#: rhodecode/templates/bookmarks/bookmarks.html:74 -#: rhodecode/templates/branches/branches.html:73 -#: rhodecode/templates/journal/journal.html:204 -#: rhodecode/templates/journal/journal.html:294 -#: rhodecode/templates/tags/tags.html:74 +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 msgid "Click to sort ascending" msgstr "点击以升序排列" -#: rhodecode/templates/index_base.html:137 -#: rhodecode/templates/admin/repos/repos.html:87 -#: rhodecode/templates/admin/users/user_edit_my_account.html:184 -#: rhodecode/templates/admin/users/users.html:108 -#: rhodecode/templates/bookmarks/bookmarks.html:75 -#: rhodecode/templates/branches/branches.html:74 -#: rhodecode/templates/journal/journal.html:205 -#: rhodecode/templates/journal/journal.html:295 -#: rhodecode/templates/tags/tags.html:75 +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 msgid "Click to sort descending" msgstr "点击以降序排列" -#: rhodecode/templates/index_base.html:138 +#: kallithea/templates/index_base.html:143 msgid "No repositories found." msgstr "" -#: rhodecode/templates/index_base.html:139 -#: rhodecode/templates/admin/repos/repos.html:89 -#: rhodecode/templates/admin/users/user_edit_my_account.html:186 -#: rhodecode/templates/admin/users/users.html:110 -#: rhodecode/templates/bookmarks/bookmarks.html:77 -#: rhodecode/templates/branches/branches.html:76 -#: rhodecode/templates/journal/journal.html:207 -#: rhodecode/templates/journal/journal.html:297 -#: rhodecode/templates/tags/tags.html:77 +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 msgid "Data error." msgstr "数据错误" -#: rhodecode/templates/index_base.html:140 -#: rhodecode/templates/admin/repos/repos.html:90 -#: rhodecode/templates/admin/users/user_edit_my_account.html:58 -#: rhodecode/templates/admin/users/user_edit_my_account.html:187 -#: rhodecode/templates/admin/users/users.html:111 -#: rhodecode/templates/bookmarks/bookmarks.html:78 -#: rhodecode/templates/branches/branches.html:77 -#: rhodecode/templates/journal/journal.html:208 -#: rhodecode/templates/journal/journal.html:298 -#: rhodecode/templates/tags/tags.html:78 +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 msgid "Loading..." msgstr "载入中..." -#: rhodecode/templates/login.html:5 rhodecode/templates/base/base.html:239 +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 msgid "Log In" msgstr "登录" -#: rhodecode/templates/login.html:21 +#: kallithea/templates/login.html:30 #, python-format msgid "Log In to %s" msgstr "" -#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20 -#: rhodecode/templates/admin/admin_log.html:5 -#: rhodecode/templates/admin/users/user_add.html:32 -#: rhodecode/templates/admin/users/user_edit.html:57 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:31 -#: rhodecode/templates/admin/users/users.html:77 -#: rhodecode/templates/base/base.html:215 -#: rhodecode/templates/summary/summary.html:123 +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 msgid "Username" msgstr "帐号" -#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29 -#: rhodecode/templates/admin/ldap/ldap.html:46 -#: rhodecode/templates/admin/users/user_add.html:41 -#: rhodecode/templates/base/base.html:224 +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 msgid "Password" msgstr "密码" -#: rhodecode/templates/login.html:50 +#: kallithea/templates/login.html:62 msgid "Remember me" msgstr "记住密码" -#: rhodecode/templates/login.html:54 +#: kallithea/templates/login.html:66 msgid "Sign In" msgstr "登录" -#: rhodecode/templates/login.html:60 +#: kallithea/templates/login.html:72 msgid "Forgot your password ?" msgstr "忘记了密码?" -#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:235 +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 msgid "Don't have an account ?" msgstr "还没有帐号?" -#: rhodecode/templates/password_reset.html:5 +#: kallithea/templates/password_reset.html:5 msgid "Password Reset" msgstr "" -#: rhodecode/templates/password_reset.html:11 -msgid "Reset your password to" -msgstr "重置密码" - -#: rhodecode/templates/password_reset.html:21 -msgid "Email address" -msgstr "邮件地址" - -#: rhodecode/templates/password_reset.html:30 -msgid "Reset my password" -msgstr "重置密码" - -#: rhodecode/templates/password_reset.html:31 +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" +msgstr "" + +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "" + +#: kallithea/templates/password_reset.html:64 msgid "Password reset link will be send to matching email address" msgstr "密码重置地址已经发送到邮件" -#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74 +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 msgid "Sign Up" msgstr "注册" -#: rhodecode/templates/register.html:11 -msgid "Sign Up to" -msgstr "注册" - -#: rhodecode/templates/register.html:38 +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:58 msgid "Re-enter password" msgstr "确认密码" -#: rhodecode/templates/register.html:47 -#: rhodecode/templates/admin/users/user_add.html:59 -#: rhodecode/templates/admin/users/user_edit.html:97 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:62 +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 msgid "First Name" msgstr "名" -#: rhodecode/templates/register.html:56 -#: rhodecode/templates/admin/users/user_add.html:68 -#: rhodecode/templates/admin/users/user_edit.html:106 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:71 +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 msgid "Last Name" msgstr "姓" -#: rhodecode/templates/register.html:65 -#: rhodecode/templates/admin/users/user_add.html:77 -#: rhodecode/templates/admin/users/user_edit.html:115 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:80 -#: rhodecode/templates/summary/summary.html:125 +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 msgid "Email" msgstr "电子邮件" -#: rhodecode/templates/register.html:76 +#: kallithea/templates/register.html:108 msgid "Your account will be activated right after registration" msgstr "注册后,帐号将启用" -#: rhodecode/templates/register.html:78 +#: kallithea/templates/register.html:110 msgid "Your account must wait for activation by administrator" msgstr "管理员审核后,你注册的帐号将被启用" -#: rhodecode/templates/repo_switcher_list.html:10 -#: rhodecode/templates/admin/defaults/defaults.html:44 -#: rhodecode/templates/admin/repos/repo_add_base.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:78 -#: rhodecode/templates/data_table/_dt_elements.html:61 -#: rhodecode/templates/summary/summary.html:77 -msgid "Private repository" -msgstr "私有版本库" - -#: rhodecode/templates/repo_switcher_list.html:12 -#: rhodecode/templates/data_table/_dt_elements.html:63 -#: rhodecode/templates/summary/summary.html:79 -msgid "Public repository" -msgstr "公共版本库" - -#: rhodecode/templates/switch_to_list.html:10 -#: rhodecode/templates/branches/branches_data.html:57 +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 msgid "There are no branches yet" msgstr "没有任何分支" -#: rhodecode/templates/switch_to_list.html:22 -#: rhodecode/templates/tags/tags_data.html:38 +#: kallithea/templates/switch_to_list.html:16 +msgid "Closed Branches" +msgstr "" + +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 msgid "There are no tags yet" msgstr "没有任何标签" -#: rhodecode/templates/switch_to_list.html:35 -#: rhodecode/templates/bookmarks/bookmarks_data.html:37 +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 msgid "There are no bookmarks yet" msgstr "无书签" -#: rhodecode/templates/admin/admin.html:5 -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/base/base.html:73 +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 msgid "Admin journal" msgstr "系统日志" -#: rhodecode/templates/admin/admin.html:10 +#: kallithea/templates/admin/admin.html:13 msgid "journal filter..." msgstr "日志过滤..." -#: rhodecode/templates/admin/admin.html:12 -#: rhodecode/templates/journal/journal.html:11 +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 msgid "filter" msgstr "过滤" -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 #, python-format msgid "%s entry" msgid_plural "%s entries" msgstr[0] "%s条" -#: rhodecode/templates/admin/admin_log.html:6 -#: rhodecode/templates/admin/repos/repos.html:79 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46 -#: rhodecode/templates/admin/users/user_edit_my_account.html:176 -#: rhodecode/templates/admin/users/users.html:87 -#: rhodecode/templates/admin/users_groups/users_groups.html:40 -#: rhodecode/templates/journal/journal.html:197 -#: rhodecode/templates/journal/journal.html:287 +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 msgid "Action" msgstr "操作" -#: rhodecode/templates/admin/admin_log.html:7 -#: rhodecode/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" msgstr "版本库" -#: rhodecode/templates/admin/admin_log.html:8 -#: rhodecode/templates/bookmarks/bookmarks.html:49 -#: rhodecode/templates/bookmarks/bookmarks_data.html:7 -#: rhodecode/templates/branches/branches.html:48 -#: rhodecode/templates/branches/branches_data.html:7 -#: rhodecode/templates/tags/tags.html:49 -#: rhodecode/templates/tags/tags_data.html:7 +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 msgid "Date" msgstr "日期" -#: rhodecode/templates/admin/admin_log.html:9 +#: kallithea/templates/admin/admin_log.html:9 msgid "From IP" msgstr "来源IP" -#: rhodecode/templates/admin/admin_log.html:63 +#: kallithea/templates/admin/admin_log.html:63 msgid "No actions yet" msgstr "无操作" -#: rhodecode/templates/admin/defaults/defaults.html:5 -#: rhodecode/templates/admin/defaults/defaults.html:25 +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "" +"Comma separated list of plugins. Order of plugins is also order in which " +"Kallithea will try to authenticate user" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "保存" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 msgid "Repositories defaults" msgstr "版本库默认设置" -#: rhodecode/templates/admin/defaults/defaults.html:11 -#: rhodecode/templates/base/base.html:80 +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 msgid "Defaults" msgstr "默认设置" -#: rhodecode/templates/admin/defaults/defaults.html:35 -#: rhodecode/templates/admin/repos/repo_add_base.html:38 +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 msgid "Type" msgstr "类型" -#: rhodecode/templates/admin/defaults/defaults.html:48 -#: rhodecode/templates/admin/repos/repo_add_base.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:82 -#: rhodecode/templates/forks/fork.html:69 +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "私有版本库" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 msgid "" "Private repositories are only visible to people explicitly added as " "collaborators." msgstr "私有版本库只对成员可见。" -#: rhodecode/templates/admin/defaults/defaults.html:55 -#: rhodecode/templates/admin/repos/repo_edit.html:87 +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 msgid "Enable statistics" msgstr "启用统计" -#: rhodecode/templates/admin/defaults/defaults.html:59 -#: rhodecode/templates/admin/repos/repo_edit.html:91 +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." msgstr "启用概况页的统计窗口" -#: rhodecode/templates/admin/defaults/defaults.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:96 +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 msgid "Enable downloads" msgstr "启用下载" -#: rhodecode/templates/admin/defaults/defaults.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:100 +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." msgstr "启用概况页的下载菜单" -#: rhodecode/templates/admin/defaults/defaults.html:75 -#: rhodecode/templates/admin/repos/repo_edit.html:105 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:64 +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 msgid "Enable locking" msgstr "启用锁定" -#: rhodecode/templates/admin/defaults/defaults.html:79 -#: rhodecode/templates/admin/repos/repo_edit.html:109 +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 msgid "Enable lock-by-pulling on repository." msgstr "启用版本库的拉取锁定" -#: rhodecode/templates/admin/defaults/defaults.html:84 -#: rhodecode/templates/admin/ldap/ldap.html:89 -#: rhodecode/templates/admin/permissions/permissions.html:122 -#: rhodecode/templates/admin/repos/repo_edit.html:141 -#: rhodecode/templates/admin/repos/repo_edit.html:166 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:72 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:96 -#: rhodecode/templates/admin/settings/hooks.html:73 -#: rhodecode/templates/admin/users/user_add.html:94 -#: rhodecode/templates/admin/users/user_edit.html:140 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:88 -#: rhodecode/templates/admin/users_groups/users_group_add.html:49 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:143 -#: rhodecode/templates/base/default_perms_box.html:53 -msgid "Save" -msgstr "保存" - -#: rhodecode/templates/admin/gists/index.html:5 -#: rhodecode/templates/base/base.html:299 -msgid "Gists" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "" +"Gist was update since you started editing. Copy your changes and click " +"%(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 #, python-format msgid "Private Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:12 +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 #, python-format msgid "Public Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:14 +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 msgid "Public Gists" msgstr "" -#: rhodecode/templates/admin/gists/index.html:31 -#: rhodecode/templates/admin/gists/show.html:24 -#: rhodecode/templates/base/base.html:302 -msgid "Create new gist" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:48 +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 msgid "Created" msgstr "" -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/index.html:53 -#: rhodecode/templates/admin/gists/show.html:43 -#: rhodecode/templates/admin/gists/show.html:45 -msgid "Expires" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/show.html:43 -msgid "never" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:68 +#: kallithea/templates/admin/gists/index.html:77 msgid "There are no gists yet" msgstr "" -#: rhodecode/templates/admin/gists/new.html:5 -#: rhodecode/templates/admin/gists/new.html:16 -msgid "New gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:37 -msgid "Gist description ..." -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:52 -msgid "Create private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:53 -msgid "Create public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:54 -#: rhodecode/templates/admin/permissions/permissions.html:123 -#: rhodecode/templates/admin/permissions/permissions.html:185 -#: rhodecode/templates/admin/repos/repo_edit.html:142 -#: rhodecode/templates/admin/repos/repo_edit.html:167 -#: rhodecode/templates/admin/repos/repo_edit.html:381 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:97 -#: rhodecode/templates/admin/settings/settings.html:115 -#: rhodecode/templates/admin/settings/settings.html:196 -#: rhodecode/templates/admin/settings/settings.html:288 -#: rhodecode/templates/admin/users/user_edit.html:141 -#: rhodecode/templates/admin/users/user_edit.html:198 -#: rhodecode/templates/admin/users/user_edit.html:246 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:89 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:144 -#: rhodecode/templates/base/default_perms_box.html:54 -#: rhodecode/templates/files/files_add.html:80 -#: rhodecode/templates/files/files_edit.html:66 -#: rhodecode/templates/pullrequests/pullrequest.html:86 +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 msgid "Reset" msgstr "重置" -#: rhodecode/templates/admin/gists/show.html:5 -msgid "gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:9 +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 msgid "Gist" msgstr "" -#: rhodecode/templates/admin/gists/show.html:36 -msgid "Public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:38 -msgid "Private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:54 -#: rhodecode/templates/admin/repos/repo_edit.html:299 -#: rhodecode/templates/changeset/changeset_file_comment.html:40 +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 msgid "Delete" msgstr "删除" -#: rhodecode/templates/admin/gists/show.html:54 -msgid "Confirm to delete this gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:63 -#: rhodecode/templates/admin/gists/show.html:84 -#: rhodecode/templates/files/files_edit.html:48 -#: rhodecode/templates/files/files_source.html:25 -#: rhodecode/templates/files/files_source.html:55 -msgid "Show as raw" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:71 +#: kallithea/templates/admin/gists/show.html:59 +msgid "Confirm to delete this Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:76 msgid "created" msgstr "" -#: rhodecode/templates/admin/ldap/ldap.html:5 -msgid "LDAP administration" -msgstr "LDAP管理员" - -#: rhodecode/templates/admin/ldap/ldap.html:11 -#: rhodecode/templates/admin/users/users.html:86 -#: rhodecode/templates/base/base.html:79 -msgid "LDAP" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:28 -msgid "Connection settings" -msgstr "连接设置" - -#: rhodecode/templates/admin/ldap/ldap.html:30 -msgid "Enable LDAP" -msgstr "启用LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:34 -msgid "Host" -msgstr "主机" - -#: rhodecode/templates/admin/ldap/ldap.html:38 -msgid "Port" -msgstr "端口" - -#: rhodecode/templates/admin/ldap/ldap.html:42 -msgid "Account" -msgstr "帐号" - -#: rhodecode/templates/admin/ldap/ldap.html:50 -msgid "Connection security" -msgstr "连接安全" - -#: rhodecode/templates/admin/ldap/ldap.html:54 -msgid "Certificate Checks" -msgstr "凭证确认" - -#: rhodecode/templates/admin/ldap/ldap.html:57 -msgid "Search settings" -msgstr "搜索设置" - -#: rhodecode/templates/admin/ldap/ldap.html:59 -msgid "Base DN" -msgstr "Base DN" - -#: rhodecode/templates/admin/ldap/ldap.html:63 -msgid "LDAP Filter" -msgstr "LDAP过滤器" - -#: rhodecode/templates/admin/ldap/ldap.html:67 -msgid "LDAP Search Scope" -msgstr "LDAP搜索范围" - -#: rhodecode/templates/admin/ldap/ldap.html:70 -msgid "Attribute mappings" -msgstr "属性映射" - -#: rhodecode/templates/admin/ldap/ldap.html:72 -msgid "Login Attribute" -msgstr "登录属性" - -#: rhodecode/templates/admin/ldap/ldap.html:76 -msgid "First Name Attribute" -msgstr "名" - -#: rhodecode/templates/admin/ldap/ldap.html:80 -msgid "Last Name Attribute" -msgstr "姓" - -#: rhodecode/templates/admin/ldap/ldap.html:84 -msgid "E-mail Attribute" -msgstr "电子邮件属性" - -#: rhodecode/templates/admin/notifications/notifications.html:5 -#: rhodecode/templates/admin/notifications/notifications.html:9 +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "我的账户" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" +msgstr "我的账户" + +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "关注的" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "拉取请求" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "我的权限" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "增加" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "删除" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "确认删除邮箱:%s" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "增加邮箱" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "新密码" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "修改你的头像" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "使用中" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "" +"Your user is in an external Source of Record; some details cannot be " +"managed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "我创建的" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "拉取请求#%s创建于%s" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "已关闭" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "确认删除拉取请求" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "无条目" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "我参与的" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "拉取请求#%s由%s创建于%s" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "没有找到记录" + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 msgid "My Notifications" msgstr "我的通知" -#: rhodecode/templates/admin/notifications/notifications.html:29 +#: kallithea/templates/admin/notifications/notifications.html:32 msgid "All" msgstr "全部" -#: rhodecode/templates/admin/notifications/notifications.html:30 +#: kallithea/templates/admin/notifications/notifications.html:33 msgid "Comments" msgstr "评论" -#: rhodecode/templates/admin/notifications/notifications.html:31 -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:8 -msgid "Pull requests" -msgstr "拉取请求" - -#: rhodecode/templates/admin/notifications/notifications.html:35 +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:38 msgid "Mark all read" msgstr "全部标记为已读" -#: rhodecode/templates/admin/notifications/notifications_data.html:39 +#: kallithea/templates/admin/notifications/notifications_data.html:40 msgid "No notifications here yet" msgstr "无通知" -#: rhodecode/templates/admin/notifications/show_notification.html:5 -#: rhodecode/templates/admin/notifications/show_notification.html:11 +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 msgid "Show notification" msgstr "显示通知" -#: rhodecode/templates/admin/notifications/show_notification.html:9 -#: rhodecode/templates/base/base.html:253 +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 msgid "Notifications" msgstr "通知" -#: rhodecode/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:5 msgid "Permissions administration" msgstr "权限管理" -#: rhodecode/templates/admin/permissions/permissions.html:11 -#: rhodecode/templates/admin/repos/repo_edit.html:151 -#: rhodecode/templates/admin/repos/repo_edit.html:158 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:81 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:88 -#: rhodecode/templates/admin/users/user_edit.html:150 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:129 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:136 -#: rhodecode/templates/base/base.html:78 +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 msgid "Permissions" msgstr "权限" -#: rhodecode/templates/admin/permissions/permissions.html:24 -msgid "Default permissions" -msgstr "默认权限" - -#: rhodecode/templates/admin/permissions/permissions.html:31 +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 msgid "Anonymous access" msgstr "匿名访问" -#: rhodecode/templates/admin/permissions/permissions.html:49 +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without need to log in. Anonymous users use %s " +"user permissions" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 msgid "" "All default permissions on each repository will be reset to chosen " -"permission, note that all custom default permission on repositories will be " -"lost" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:50 -#: rhodecode/templates/admin/permissions/permissions.html:63 -#: rhodecode/templates/admin/permissions/permissions.html:77 +"permission, note that all custom default permission on repositories will " +"be lost" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 msgid "Overwrite existing settings" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:62 +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "版本库组" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 msgid "" "All default permissions on each repository group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 msgid "User group" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:76 +#: kallithea/templates/admin/permissions/permissions_globals.html:53 msgid "" "All default permissions on each user group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:83 +#: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" msgstr "建立版本库" -#: rhodecode/templates/admin/permissions/permissions.html:91 +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "" +"Write permission to repository groups allows creating repositories inside" +" that group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 msgid "User group creation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:99 +#: kallithea/templates/admin/permissions/permissions_globals.html:85 msgid "Repository forking" msgstr "版本库复刻" -#: rhodecode/templates/admin/permissions/permissions.html:107 +#: kallithea/templates/admin/permissions/permissions_globals.html:93 msgid "Registration" msgstr "注册" -#: rhodecode/templates/admin/permissions/permissions.html:115 +#: kallithea/templates/admin/permissions/permissions_globals.html:101 msgid "External auth account activation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:133 -msgid "Default User Permissions" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:144 -#: rhodecode/templates/admin/users/user_edit.html:207 -msgid "Allowed IP addresses" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:158 -#: rhodecode/templates/admin/repos/repo_edit.html:340 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#: rhodecode/templates/admin/users/user_edit.html:175 -#: rhodecode/templates/admin/users/user_edit.html:220 -#: rhodecode/templates/admin/users_groups/users_groups.html:54 -#: rhodecode/templates/data_table/_dt_elements.html:122 -#: rhodecode/templates/data_table/_dt_elements.html:136 -msgid "delete" -msgstr "删除" - -#: rhodecode/templates/admin/permissions/permissions.html:159 -#: rhodecode/templates/admin/users/user_edit.html:221 +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 #, python-format msgid "Confirm to delete this ip: %s" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:165 -#: rhodecode/templates/admin/users/user_edit.html:227 +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 msgid "All IP addresses are allowed" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:176 -#: rhodecode/templates/admin/users/user_edit.html:238 +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:184 -#: rhodecode/templates/admin/repos/repo_add_base.html:73 -#: rhodecode/templates/admin/repos/repo_edit.html:380 -#: rhodecode/templates/admin/users/user_edit.html:197 -#: rhodecode/templates/admin/users/user_edit.html:245 -msgid "Add" -msgstr "增加" - -#: rhodecode/templates/admin/repos/repo_add.html:12 -#: rhodecode/templates/admin/repos/repo_add.html:16 -#: rhodecode/templates/base/base.html:74 rhodecode/templates/base/base.html:88 -#: rhodecode/templates/base/base.html:116 -#: rhodecode/templates/base/base.html:275 -msgid "Repositories" -msgstr "版本库" - -#: rhodecode/templates/admin/repos/repo_add.html:19 -msgid "Add new" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:20 -#: rhodecode/templates/summary/summary.html:96 -#: rhodecode/templates/summary/summary.html:97 -msgid "Clone from" -msgstr "克隆自" - -#: rhodecode/templates/admin/repos/repo_add_base.html:24 -#: rhodecode/templates/admin/repos/repo_edit.html:45 -msgid "Optional http[s] url from which repository should be cloned." -msgstr "可选的,指定版本库应该从哪个http[s]地址克隆。" - -#: rhodecode/templates/admin/repos/repo_add_base.html:33 -#: rhodecode/templates/forks/fork.html:51 -msgid "Optionaly select a group to put this repository into." -msgstr "可选的,选择一个组将版本库放到其中" - -#: rhodecode/templates/admin/repos/repo_add_base.html:42 -msgid "Type of repository to create." -msgstr "要创建的版本库类型" - -#: rhodecode/templates/admin/repos/repo_add_base.html:47 -#: rhodecode/templates/admin/repos/repo_edit.html:59 -#: rhodecode/templates/forks/fork.html:38 -msgid "Landing revision" -msgstr "默认修订" - -#: rhodecode/templates/admin/repos/repo_add_base.html:51 -#: rhodecode/templates/admin/repos/repo_edit.html:63 -#: rhodecode/templates/forks/fork.html:42 -msgid "Default revision for files page, downloads, whoosh and readme" -msgstr "文件浏览、下载、whoosh和README的默认修订版本" - -#: rhodecode/templates/admin/repos/repo_add_base.html:60 -#: rhodecode/templates/admin/repos/repo_edit.html:72 -#: rhodecode/templates/forks/fork.html:60 -msgid "" -"Keep it short and to the point. Use a README file for longer descriptions." -msgstr "保持简短。用README文件来写更长的描述。" - -#: rhodecode/templates/admin/repos/repo_edit.html:8 -msgid "Edit repository" -msgstr "编辑版本库" - -#: rhodecode/templates/admin/repos/repo_edit.html:12 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:11 -#: rhodecode/templates/base/base.html:81 -#: rhodecode/templates/base/base.html:134 -#: rhodecode/templates/summary/summary.html:212 +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "组名" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "上级组" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 msgid "Settings" msgstr "设置" -#: rhodecode/templates/admin/repos/repo_edit.html:36 -msgid "Non-changeable id" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:41 -msgid "Clone uri" -msgstr "克隆地址" - -#: rhodecode/templates/admin/repos/repo_edit.html:54 -msgid "Optional select a group to put this repository into." -msgstr "可选的,选择一个组将版本库放到其中" - -#: rhodecode/templates/admin/repos/repo_edit.html:119 -msgid "Change owner of this repository." -msgstr "修改这个版本库的所有者" - -#: rhodecode/templates/admin/repos/repo_edit.html:177 -msgid "Advanced settings" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:180 -msgid "Statistics" -msgstr "统计" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Reset current statistics" -msgstr "重置统计" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Confirm to remove current statistics" -msgstr "确认移除当前统计" - -#: rhodecode/templates/admin/repos/repo_edit.html:187 -msgid "Fetched to rev" -msgstr "获取到修订" - -#: rhodecode/templates/admin/repos/repo_edit.html:188 -msgid "Stats gathered" -msgstr "已收集的统计" - -#: rhodecode/templates/admin/repos/repo_edit.html:196 -msgid "Remote" -msgstr "远程" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Pull changes from remote location" -msgstr "从远程路径拉取修订集" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Confirm to pull changes from remote side" -msgstr "确认从远程拉取修订集" - -#: rhodecode/templates/admin/repos/repo_edit.html:211 -msgid "Cache" -msgstr "缓存" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Invalidate repository cache" -msgstr "清除版本库缓存" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Confirm to invalidate repository cache" -msgstr "确认清除版本库缓存" - -#: rhodecode/templates/admin/repos/repo_edit.html:218 -msgid "" -"Manually invalidate cache for this repository. On first access repository " -"will be cached again" -msgstr "手动清除版本库缓存。之后第一次访问的时候将重建缓存" - -#: rhodecode/templates/admin/repos/repo_edit.html:223 -msgid "List of cached values" -msgstr "缓存值列表" - -#: rhodecode/templates/admin/repos/repo_edit.html:226 -msgid "Prefix" -msgstr "前缀" - -#: rhodecode/templates/admin/repos/repo_edit.html:227 -msgid "Key" -msgstr "键" - -#: rhodecode/templates/admin/repos/repo_edit.html:228 -#: rhodecode/templates/admin/users/user_add.html:86 -#: rhodecode/templates/admin/users/user_edit.html:124 -#: rhodecode/templates/admin/users/users.html:84 -#: rhodecode/templates/admin/users_groups/users_group_add.html:41 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 -#: rhodecode/templates/admin/users_groups/users_groups.html:39 -msgid "Active" -msgstr "启用" - -#: rhodecode/templates/admin/repos/repo_edit.html:243 -#: rhodecode/templates/base/base.html:292 -#: rhodecode/templates/base/base.html:293 -msgid "Public journal" -msgstr "公共日志" - -#: rhodecode/templates/admin/repos/repo_edit.html:249 -msgid "Remove from public journal" -msgstr "从公共日志删除" - -#: rhodecode/templates/admin/repos/repo_edit.html:251 -msgid "Add to public journal" -msgstr "添加到公共日志" - -#: rhodecode/templates/admin/repos/repo_edit.html:256 -msgid "" -"All actions made on this repository will be accessible to everyone in public" -" journal" -msgstr "任何人都可以在公共日志上看到这个版本库上的所有动作" - -#: rhodecode/templates/admin/repos/repo_edit.html:263 -msgid "Locking" -msgstr "锁定" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Unlock locked repo" -msgstr "解锁版本库" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Confirm to unlock repository" -msgstr "确认解锁版本库" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Lock repo" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Confirm to lock repository" -msgstr "确认锁定版本库" - -#: rhodecode/templates/admin/repos/repo_edit.html:272 -msgid "Repository is not locked" -msgstr "版本库未锁定" - -#: rhodecode/templates/admin/repos/repo_edit.html:277 -msgid "" -"Force locking on repository. Works only when anonymous access is disabled" -msgstr "强制锁定版本库。只有在禁止匿名访问时候才有效" - -#: rhodecode/templates/admin/repos/repo_edit.html:284 -msgid "Set as fork of" -msgstr "设置复刻自" - -#: rhodecode/templates/admin/repos/repo_edit.html:289 -msgid "Set" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:293 -msgid "Manually set this repository as a fork of another from the list" -msgstr "从列表中手动设置这个版本库复刻自另一版本库" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Remove this repository" -msgstr "删除版本库" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Confirm to delete this repository" -msgstr "确认删除版本库" - -#: rhodecode/templates/admin/repos/repo_edit.html:310 -#, python-format -msgid "this repository has %s fork" -msgid_plural "this repository has %s forks" -msgstr[0] "" - -#: rhodecode/templates/admin/repos/repo_edit.html:311 -msgid "Detach forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:312 -msgid "Delete forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:315 -msgid "" -"This repository will be renamed in a special way in order to be unaccesible " -"for RhodeCode and VCS systems. If you need to fully delete it from file " -"system please do it manually" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:329 -msgid "Extra fields" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:341 -#, python-format -msgid "Confirm to delete this field: %s" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:355 -msgid "New field key" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:363 -msgid "New field label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:366 -msgid "Enter short label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:372 -msgid "New field description" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:375 -msgid "Enter description of a field" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:3 -msgid "none" -msgstr "无" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:4 -msgid "read" -msgstr "读" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:5 -msgid "write" -msgstr "写" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:6 -msgid "admin" -msgstr "管理" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:7 -msgid "member" -msgstr "成员" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:16 -msgid "private repository" -msgstr "私有版本库" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:19 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:28 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:20 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:35 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:20 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:35 -msgid "default" -msgstr "默认" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:33 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:58 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:25 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:55 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:25 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:55 -msgid "revoke" -msgstr "移除" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:83 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:81 -msgid "Add another member" -msgstr "添加成员" - -#: rhodecode/templates/admin/repos/repos.html:5 -msgid "Repositories administration" -msgstr "版本库管理员" - -#: rhodecode/templates/admin/repos/repos.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account.html:185 -#: rhodecode/templates/admin/users/users.html:109 -#: rhodecode/templates/bookmarks/bookmarks.html:76 -#: rhodecode/templates/branches/branches.html:75 -#: rhodecode/templates/journal/journal.html:206 -#: rhodecode/templates/journal/journal.html:296 -#: rhodecode/templates/tags/tags.html:76 -msgid "No records found." -msgstr "没有找到记录" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:87 -msgid "apply to children" -msgstr "应用到成员" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:88 -msgid "" -"Set or revoke permission to all children of that group, including non-" -"private repositories and other groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:4 -#, python-format -msgid "%s Group Dashboard" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:9 -msgid "Home" -msgstr "首页" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:13 -msgid "with" -msgstr "有" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5 -msgid "Add repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:16 -#: rhodecode/templates/base/base.html:75 rhodecode/templates/base/base.html:91 -msgid "Repository groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:13 -msgid "Add new repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:51 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:56 -msgid "Group parent" -msgstr "上级组" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:59 -msgid "save" -msgstr "保存" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5 -msgid "Edit repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:13 -#, python-format -msgid "Edit repository group %s" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:27 -msgid "Add child group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:68 -msgid "" -"Enable lock-by-pulling on group. This option will be applied to all other " -"groups and repositories inside" -msgstr "启用组的拉取锁定。这个选项将应用到组内的其他组和版本库" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5 -msgid "Repository groups administration" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:45 -msgid "Number of toplevel repositories" -msgstr "顶层版本库数量" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:64 -#: rhodecode/templates/admin/users_groups/users_groups.html:48 -#: rhodecode/templates/changeset/changeset_file_comment.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:171 -msgid "Edit" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:65 -#: rhodecode/templates/admin/users_groups/users_groups.html:49 -#: rhodecode/templates/base/perms_summary.html:29 -#: rhodecode/templates/base/perms_summary.html:60 -#: rhodecode/templates/base/perms_summary.html:62 -#: rhodecode/templates/data_table/_dt_elements.html:116 -#: rhodecode/templates/data_table/_dt_elements.html:117 -#: rhodecode/templates/data_table/_dt_elements.html:130 -#: rhodecode/templates/data_table/_dt_elements.html:131 -msgid "edit" -msgstr "编辑" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "创建于" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 #, python-format msgid "Confirm to delete this group: %s with %s repository" msgid_plural "Confirm to delete this group: %s with %s repositories" msgstr[0] "确认删除这个版本库组:%s包含%s个版本库" -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:78 -msgid "There are no repository groups yet" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:5 -#: rhodecode/templates/admin/settings/settings.html:5 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "无" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "读" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "写" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "管理" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "默认" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "移除" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "应用到成员" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "" +"Set or revoke permission to all children of that group, including non-" +"private repositories and other groups if selected." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "" +"Enable lock-by-pulling on group. This option will be applied to all other" +" groups and repositories inside" +msgstr "启用组的拉取锁定。这个选项将应用到组内的其他组和版本库" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "%s Repository group dashboard" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "首页" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "有" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "顶层版本库数量" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "添加版本库" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "克隆自" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "可选的,指定版本库应该从哪个http[s]地址克隆。" + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "保持简短。用README文件来写更长的描述。" + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "可选的,选择一个组将版本库放到其中" + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "要创建的版本库类型" + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "默认修订" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is beeing created, you will be redirected " +"when this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:42 +msgid "" +"We're sorry but error occured during this operation. Please check your " +"Kallithea server logs, or contact administrator." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, python-format +msgid "%s repository settings" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +msgid "Remote" +msgstr "远程" + +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "统计" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "复刻自" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "从列表中手动设置这个版本库复刻自另一版本库" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Remove from public journal" +msgstr "从公共日志删除" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +msgid "Add to public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 +msgid "" +"All actions made on this repository will be accessible to everyone in " +"public journal" +msgstr "任何人都可以在公共日志上看到这个版本库上的所有动作" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 +msgid "Confirm to unlock repository" +msgstr "确认解锁版本库" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 +msgid "Confirm to lock repository" +msgstr "确认锁定版本库" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 +msgid "Repository is not locked" +msgstr "版本库未锁定" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 +msgid "" +"Force locking on repository. Works only when anonymous access is " +"disabled. Trigering a pull locks repository by user who pulled, only the " +"same user can unlock by doing a push" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "确认删除版本库:%s" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +msgid "Delete this repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 +#, python-format +msgid "this repository has %s fork" +msgid_plural "this repository has %s forks" +msgstr[0] "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 +msgid "Detach forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 +msgid "Delete forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "" +"This repository will be renamed in a special way in order to be " +"unaccesible for Kallithea and VCS systems. If you need to fully delete it" +" from file system please do it manually" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "清除版本库缓存" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "确认清除版本库缓存" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 +msgid "" +"Manually invalidate cache for this repository. On first access repository" +" will be cached again" +msgstr "手动清除版本库缓存。之后第一次访问的时候将重建缓存" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "缓存值列表" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "前缀" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "键" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "启用" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#, python-format +msgid "Confirm to delete this field: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 +msgid "New field key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 +msgid "New field label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 +msgid "Enter short label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 +msgid "New field description" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +msgid "Enter description of a field" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 +msgid "private repository" +msgstr "私有版本库" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "从远程路径拉取修订集" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "确认从远程拉取修订集" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 +msgid "" +"In case this repository is renamed or moved into another group the " +"repository url changes.\n" +" Using above url guarantees that this " +"repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases" +" that you need to hardcode the url into 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "克隆地址" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "编辑" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "可选的,选择一个组将版本库放到其中" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "文件浏览、下载、whoosh和README的默认修订版本" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "修改这个版本库的所有者" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "确认移除当前统计" + +#: kallithea/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "版本库管理员" + +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 msgid "Settings administration" msgstr "系统设置" -#: rhodecode/templates/admin/settings/hooks.html:24 -msgid "Built in hooks - read only" -msgstr "内建钩子 - 只读" - -#: rhodecode/templates/admin/settings/hooks.html:40 +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "钩子" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:16 +msgid "SMTP auth" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:39 +msgid "Send" +msgstr "发送" + +#: kallithea/templates/admin/settings/settings_global.html:8 +msgid "Site branding" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:18 +msgid "HTTP authentication realm" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:27 +msgid "Google Analytics code" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:50 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 +msgid "Save settings" +msgstr "保存设置" + +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "" +"Hooks can be used to trigger actions on certain events such as push / " +"pull. They can trigger Python functions or external applications." +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 msgid "Custom hooks" msgstr "自定义钩子" -#: rhodecode/templates/admin/settings/hooks.html:56 -msgid "remove" -msgstr "删除" - -#: rhodecode/templates/admin/settings/hooks.html:88 +#: kallithea/templates/admin/settings/settings_hooks.html:69 msgid "Failed to remove hook" msgstr "移除钩子失败" -#: rhodecode/templates/admin/settings/settings.html:26 -msgid "Remap and rescan repositories" -msgstr "重新扫描并映射版本库" - -#: rhodecode/templates/admin/settings/settings.html:34 +#: kallithea/templates/admin/settings/settings_mapping.html:6 msgid "Rescan option" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:40 +#: kallithea/templates/admin/settings/settings_mapping.html:11 +msgid "Destroy old data" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:13 msgid "" -"In case a repository was deleted from filesystem and there are leftovers in " -"the database check this option to scan obsolete data in database and remove " -"it." -msgstr "如果版本库已经从文件系统删除,但数据库仍然有遗留信息,请勾选该项进行清理" - -#: rhodecode/templates/admin/settings/settings.html:41 -msgid "Destroy old data" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:43 +"In case a repository was deleted from filesystem and it still exists in " +"the database check this option to scan obsolete data in database and " +"remove it." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 msgid "" -"Rescan repositories location for new repositories. Also deletes obsolete if " -"`destroy` flag is checked " -msgstr "重新扫描版本库路径以发现新版本库。 同时删除过时的,如果设置有 `destroy` 标志" - -#: rhodecode/templates/admin/settings/settings.html:48 -msgid "Rescan repositories" -msgstr "重新扫描版本库" - -#: rhodecode/templates/admin/settings/settings.html:54 -msgid "Whoosh indexing" -msgstr "Whoosh索引" - -#: rhodecode/templates/admin/settings/settings.html:62 +"Each cache data for repositories will be cleaned with this option " +"selected. Use this to reload data and clear cache keys." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 +msgid "" +"Verify if Kallitheas GIT hooks are installed for each repository. Current" +" hooks will be updated to latest version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:7 msgid "Index build option" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:67 +#: kallithea/templates/admin/settings/settings_search.html:12 msgid "Build from scratch" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:73 +#: kallithea/templates/admin/settings/settings_search.html:15 +msgid "" +"This option completely reindex all the files within Kallithea for proper " +"fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:21 msgid "Reindex" msgstr "重新索引" -#: rhodecode/templates/admin/settings/settings.html:79 -msgid "Global application settings" -msgstr "全局设置" - -#: rhodecode/templates/admin/settings/settings.html:88 -msgid "Site branding" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:97 -msgid "HTTP authentication realm" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:106 -msgid "Google Analytics code" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:114 -#: rhodecode/templates/admin/settings/settings.html:195 -#: rhodecode/templates/admin/settings/settings.html:287 -msgid "Save settings" -msgstr "保存设置" - -#: rhodecode/templates/admin/settings/settings.html:121 -msgid "Visualisation settings" -msgstr "可视化设置" - -#: rhodecode/templates/admin/settings/settings.html:129 +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 +msgid "Web" +msgstr "网络" + +#: kallithea/templates/admin/settings/settings_vcs.html:11 +msgid "Require SSL for vcs operations" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:13 +msgid "" +"Activate to set Kallithea to require SSL for pushing or pulling. If SSL " +"certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 +msgid "Show repository size after push" +msgstr "推送后显示版本库大小" + +#: kallithea/templates/admin/settings/settings_vcs.html:28 +msgid "Log user push commands" +msgstr "记录用户推送命令" + +#: kallithea/templates/admin/settings/settings_vcs.html:32 +msgid "Log user pull commands" +msgstr "记录用户拉取命令" + +#: kallithea/templates/admin/settings/settings_vcs.html:36 +msgid "Update repository after push (hg update)" +msgstr "推送后更新版本库(hg update)" + +#: kallithea/templates/admin/settings/settings_vcs.html:42 +msgid "Mercurial Extensions" +msgstr "Mercurial扩展" + +#: kallithea/templates/admin/settings/settings_vcs.html:47 +msgid "Enable largefiles extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:51 +msgid "Enable hgsubversion extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:53 +msgid "" +"Requires hgsubversion library to be installed. Allows cloning remote SVN " +"repositories and migrates them to Mercurial type." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 +msgid "Repositories location" +msgstr "版本库路径" + +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting" +" take effect." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:72 +msgid "" +"Filesystem location where repositories should be stored. After changing " +"this value a restart and rescan of the repository folder are required." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:8 msgid "General" msgstr "通用" -#: rhodecode/templates/admin/settings/settings.html:134 +#: kallithea/templates/admin/settings/settings_visual.html:13 msgid "Use repository extra fields" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:136 +#: kallithea/templates/admin/settings/settings_visual.html:15 msgid "Allows storing additional customized fields per repository." msgstr "" -#: rhodecode/templates/admin/settings/settings.html:139 -msgid "Show RhodeCode version" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:141 -msgid "Shows or hides displayed version of RhodeCode in the footer" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:146 +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:30 +msgid "" +"Gravatar url allows you to use other avatar server application.\n" +" Following " +"variables of the URL will be replaced accordingly.\n" +" {scheme} " +"'http' or 'https' sent from running Kallithea server,\n" +" {email} user " +"email,\n" +" {md5email} md5 " +"hash of the user email (like at gravatar.com),\n" +" {size} size " +"of the image that is expected from the server application,\n" +" {netloc} " +"network location/server host of running Kallithea server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:42 +msgid "" +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}'," +" available vars:\n" +" {scheme} 'http' " +"or 'https' sent from running Kallithea server,\n" +" {user} current " +"user username,\n" +" {netloc} network " +"location/server host of running Kallithea server,\n" +" {repo} full " +"repository name,\n" +" {repoid} ID of " +"repository, can be used to contruct clone-by-id" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:54 msgid "Dashboard items" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:150 +#: kallithea/templates/admin/settings/settings_visual.html:58 msgid "" -"Number of items displayed in lightweight dashboard before pagination is " +"Number of items displayed in the main page dashboard before pagination is" +" shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:68 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: rhodecode/templates/admin/settings/settings.html:155 +#: kallithea/templates/admin/settings/settings_visual.html:74 msgid "Icons" msgstr "图标" -#: rhodecode/templates/admin/settings/settings.html:160 +#: kallithea/templates/admin/settings/settings_visual.html:79 msgid "Show public repo icon on repositories" msgstr "显示公共版本库图标" -#: rhodecode/templates/admin/settings/settings.html:164 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Show private repo icon on repositories" msgstr "显示私有版本库图标" -#: rhodecode/templates/admin/settings/settings.html:166 -msgid "Show public/private icons next to repositories names" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:172 +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:91 msgid "Meta-Tagging" msgstr "元标记" -#: rhodecode/templates/admin/settings/settings.html:177 -msgid "Stylify recognised metatags:" -msgstr "样式化识别的元标记" - -#: rhodecode/templates/admin/settings/settings.html:204 -msgid "VCS settings" -msgstr "版本控制系统设置" - -#: rhodecode/templates/admin/settings/settings.html:213 -msgid "Web" -msgstr "网络" - -#: rhodecode/templates/admin/settings/settings.html:218 -msgid "Require SSL for vcs operations" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:220 +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:110 msgid "" -"RhodeCode will require SSL for pushing or pulling. If SSL is missing it will" -" return HTTP Error 406: Not Acceptable" -msgstr "勾选后RhodeCode将要求使用SSL进行推送和拉取。如果没有使用SSL将返回HTTP 406错误:Not Acceptable" - -#: rhodecode/templates/admin/settings/settings.html:226 -msgid "Hooks" -msgstr "钩子" - -#: rhodecode/templates/admin/settings/settings.html:231 -msgid "Update repository after push (hg update)" -msgstr "推送后更新版本库(hg update)" - -#: rhodecode/templates/admin/settings/settings.html:235 -msgid "Show repository size after push" -msgstr "推送后显示版本库大小" - -#: rhodecode/templates/admin/settings/settings.html:239 -msgid "Log user push commands" -msgstr "记录用户推送命令" - -#: rhodecode/templates/admin/settings/settings.html:243 -msgid "Log user pull commands" -msgstr "记录用户拉取命令" - -#: rhodecode/templates/admin/settings/settings.html:247 -msgid "Advanced setup" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:252 -msgid "Mercurial Extensions" -msgstr "Mercurial扩展" - -#: rhodecode/templates/admin/settings/settings.html:257 -msgid "Enable largefiles extension" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:261 -msgid "Enable hgsubversion extension" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:263 -msgid "" -"Requires hgsubversion library installed. Allows cloning from svn remote " -"locations" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:274 -msgid "Repositories location" -msgstr "版本库路径" - -#: rhodecode/templates/admin/settings/settings.html:279 -msgid "" -"Click to unlock. You must restart RhodeCode in order to make this setting " -"take effect." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:280 -#: rhodecode/templates/base/base.html:143 -msgid "Unlock" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:282 -msgid "" -"Location where repositories are stored. After changing this value a restart," -" and rescan is required" -msgstr "版本库存储路径。 修改后需要重启和重新扫描" - -#: rhodecode/templates/admin/settings/settings.html:303 -msgid "Test Email" -msgstr "测试邮件" - -#: rhodecode/templates/admin/settings/settings.html:311 -msgid "Email to" -msgstr "发送到" - -#: rhodecode/templates/admin/settings/settings.html:319 -msgid "Send" -msgstr "发送" - -#: rhodecode/templates/admin/settings/settings.html:325 -msgid "System Info and Packages" -msgstr "系统和软件包信息" - -#: rhodecode/templates/admin/settings/settings.html:328 -#: rhodecode/templates/changelog/changelog.html:51 -msgid "Show" -msgstr "显示" - -#: rhodecode/templates/admin/users/user_add.html:5 +"Parses meta tags from repository description field and turns them into " +"colored tags." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 +msgid "Add user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 +msgid "User groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 +#, python-format +msgid "%s user group settings" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "默认权限" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 +msgid "Members" +msgstr "成员" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 +#, python-format +msgid "User Group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 +#, python-format +msgid "Confirm to delete this user group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "还没有成员" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "移除全部项目" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "启用成员" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "添加全部项目" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 msgid "Add user" msgstr "添加用户" -#: rhodecode/templates/admin/users/user_add.html:10 -#: rhodecode/templates/admin/users/user_edit.html:11 -#: rhodecode/templates/base/base.html:76 +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 msgid "Users" msgstr "用户" -#: rhodecode/templates/admin/users/user_add.html:12 -#: rhodecode/templates/admin/users/users.html:23 -msgid "Add new user" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:50 +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:53 msgid "Password confirmation" msgstr "确认密码" -#: rhodecode/templates/admin/users/user_edit.html:5 -msgid "Edit user" -msgstr "编辑用户" - -#: rhodecode/templates/admin/users/user_edit.html:13 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 -#, python-format -msgid "Edit %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:34 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:10 -msgid "Change your avatar at" -msgstr "修改你的头像" - -#: rhodecode/templates/admin/users/user_edit.html:35 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:11 -msgid "Using" -msgstr "使用中" - -#: rhodecode/templates/admin/users/user_edit.html:43 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:20 -msgid "API key" -msgstr "API密钥" - -#: rhodecode/templates/admin/users/user_edit.html:50 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:25 -msgid "Current IP" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:70 -msgid "LDAP DN" -msgstr "LDAP DN" - -#: rhodecode/templates/admin/users/user_edit.html:79 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:44 -msgid "New password" -msgstr "新密码" - -#: rhodecode/templates/admin/users/user_edit.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:53 +#: kallithea/templates/admin/users/user_edit.html:5 +#, python-format +msgid "%s user settings" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "确认删除用户:%s" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 +#, python-format +msgid "" +"This user is in an external Source of Record (%s); some details cannot be" +" managed here." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 msgid "New password confirmation" msgstr "确认新密码" -#: rhodecode/templates/admin/users/user_edit.html:163 -msgid "Email addresses" -msgstr "邮件地址" - -#: rhodecode/templates/admin/users/user_edit.html:176 -#, python-format -msgid "Confirm to delete this email: %s" -msgstr "确认删除邮箱:%s" - -#: rhodecode/templates/admin/users/user_edit.html:190 -msgid "New email address" -msgstr "增加邮箱" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:5 -#: rhodecode/templates/base/base.html:254 -msgid "My account" -msgstr "我的账户" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:9 -msgid "My Account" -msgstr "我的账户" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:35 -msgid "My permissions" -msgstr "我的权限" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:38 -#: rhodecode/templates/journal/journal.html:54 -msgid "My repos" -msgstr "我的版本库" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:41 -msgid "My pull requests" -msgstr "我的拉取请求" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:4 -msgid "Show closed pull requests" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:6 -msgid "Opened by me" -msgstr "我创建的" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "拉取请求#%s创建于%s" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:17 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:45 -#: rhodecode/templates/pullrequests/pullrequest_data.html:11 -#: rhodecode/templates/pullrequests/pullrequest_show.html:27 -#: rhodecode/templates/pullrequests/pullrequest_show.html:42 -msgid "Closed" -msgstr "已关闭" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:23 -msgid "Confirm to delete this pull request" -msgstr "确认删除拉取请求" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:30 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:51 -msgid "Nothing here yet" -msgstr "无条目" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:34 -msgid "I participate in" -msgstr "我参与的" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:42 -#: rhodecode/templates/pullrequests/pullrequest_data.html:8 -#, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "拉取请求#%s由%s创建于%s" - -#: rhodecode/templates/admin/users/users.html:5 +#: kallithea/templates/admin/users/users.html:5 msgid "Users administration" msgstr "用户管理员" -#: rhodecode/templates/admin/users/users.html:9 +#: kallithea/templates/admin/users/users.html:13 msgid "users" msgstr "用户" -#: rhodecode/templates/admin/users/users.html:80 +#: kallithea/templates/admin/users/users.html:54 msgid "Firstname" msgstr "" -#: rhodecode/templates/admin/users/users.html:81 +#: kallithea/templates/admin/users/users.html:55 msgid "Lastname" msgstr "" -#: rhodecode/templates/admin/users/users.html:82 +#: kallithea/templates/admin/users/users.html:56 msgid "Last login" msgstr "" -#: rhodecode/templates/admin/users_groups/users_group_add.html:5 -msgid "Add user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:10 -#: rhodecode/templates/admin/users_groups/users_groups.html:11 -#: rhodecode/templates/base/base.html:77 rhodecode/templates/base/base.html:94 -msgid "User groups" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:12 -#: rhodecode/templates/admin/users_groups/users_groups.html:26 -msgid "Add new user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 -msgid "Edit user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 -msgid "UserGroups" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 -#: rhodecode/templates/admin/users_groups/users_groups.html:38 -msgid "Members" -msgstr "成员" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 -msgid "Chosen group members" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 -msgid "Remove all elements" -msgstr "移除全部项目" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 -msgid "Available members" -msgstr "启用成员" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 -msgid "Add all elements" -msgstr "添加全部项目" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:109 -msgid "No members yet" -msgstr "还没有成员" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:117 -msgid "Global Permissions" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:5 -msgid "User groups administration" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:55 -#, python-format -msgid "Confirm to delete this user group: %s" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:62 -msgid "There are no user groups yet" -msgstr "" - -#: rhodecode/templates/base/base.html:42 +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "" + +#: kallithea/templates/base/base.html:37 #, python-format msgid "Server instance: %s" msgstr "" -#: rhodecode/templates/base/base.html:52 -msgid "Report a bug" -msgstr "" - -#: rhodecode/templates/base/base.html:121 -#: rhodecode/templates/data_table/_dt_elements.html:9 -#: rhodecode/templates/data_table/_dt_elements.html:11 -#: rhodecode/templates/data_table/_dt_elements.html:13 -#: rhodecode/templates/summary/summary.html:8 +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 msgid "Summary" msgstr "概况" -#: rhodecode/templates/base/base.html:122 -#: rhodecode/templates/changelog/changelog.html:15 -#: rhodecode/templates/data_table/_dt_elements.html:17 -#: rhodecode/templates/data_table/_dt_elements.html:19 -#: rhodecode/templates/data_table/_dt_elements.html:21 +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 msgid "Changelog" msgstr "修订记录" -#: rhodecode/templates/base/base.html:123 -#: rhodecode/templates/data_table/_dt_elements.html:25 -#: rhodecode/templates/data_table/_dt_elements.html:27 -#: rhodecode/templates/data_table/_dt_elements.html:29 -#: rhodecode/templates/files/files.html:12 +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 msgid "Files" msgstr "浏览" -#: rhodecode/templates/base/base.html:125 +#: kallithea/templates/base/base.html:149 msgid "Switch To" msgstr "" -#: rhodecode/templates/base/base.html:127 -#: rhodecode/templates/base/base.html:279 -msgid "loading..." -msgstr "载入中..." - -#: rhodecode/templates/base/base.html:131 +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 msgid "Options" msgstr "选项" -#: rhodecode/templates/base/base.html:137 -#: rhodecode/templates/forks/forks_data.html:21 +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 msgid "Compare fork" msgstr "比较复刻" -#: rhodecode/templates/base/base.html:139 -#: rhodecode/templates/base/base.html:312 -#: rhodecode/templates/search/search.html:14 -#: rhodecode/templates/search/search.html:54 +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "比较显示" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 msgid "Search" msgstr "搜索" -#: rhodecode/templates/base/base.html:145 +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "" + +#: kallithea/templates/base/base.html:176 msgid "Lock" msgstr "" -#: rhodecode/templates/base/base.html:153 +#: kallithea/templates/base/base.html:184 msgid "Follow" msgstr "" -#: rhodecode/templates/base/base.html:154 +#: kallithea/templates/base/base.html:185 msgid "Unfollow" msgstr "" -#: rhodecode/templates/base/base.html:157 -#: rhodecode/templates/data_table/_dt_elements.html:33 -#: rhodecode/templates/data_table/_dt_elements.html:35 -#: rhodecode/templates/data_table/_dt_elements.html:37 -#: rhodecode/templates/data_table/_dt_elements.html:74 -#: rhodecode/templates/forks/fork.html:9 +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 msgid "Fork" msgstr "复刻" -#: rhodecode/templates/base/base.html:159 +#: kallithea/templates/base/base.html:190 msgid "Create Pull Request" msgstr "" -#: rhodecode/templates/base/base.html:165 -msgid "Show Pull Requests" -msgstr "" - -#: rhodecode/templates/base/base.html:165 -msgid "Pull Requests" -msgstr "" - -#: rhodecode/templates/base/base.html:202 +#: kallithea/templates/base/base.html:196 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "" + +#: kallithea/templates/base/base.html:233 msgid "Not logged in" msgstr "" -#: rhodecode/templates/base/base.html:209 +#: kallithea/templates/base/base.html:240 msgid "Login to your account" msgstr "登录" -#: rhodecode/templates/base/base.html:232 +#: kallithea/templates/base/base.html:263 msgid "Forgot password ?" msgstr "忘记密码?" -#: rhodecode/templates/base/base.html:255 +#: kallithea/templates/base/base.html:286 msgid "Log Out" msgstr "退出" -#: rhodecode/templates/base/base.html:274 -msgid "Switch repository" -msgstr "切换版本库" - -#: rhodecode/templates/base/base.html:286 +#: kallithea/templates/base/base.html:311 msgid "Show recent activity" msgstr "" -#: rhodecode/templates/base/base.html:287 -#: rhodecode/templates/journal/journal.html:4 +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 msgid "Journal" msgstr "日志" -#: rhodecode/templates/base/base.html:298 +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "公共日志" + +#: kallithea/templates/base/base.html:323 msgid "Show public gists" msgstr "" -#: rhodecode/templates/base/base.html:303 +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "" + +#: kallithea/templates/base/base.html:328 msgid "All public gists" msgstr "" -#: rhodecode/templates/base/base.html:305 +#: kallithea/templates/base/base.html:330 msgid "My public gists" msgstr "" -#: rhodecode/templates/base/base.html:306 +#: kallithea/templates/base/base.html:331 msgid "My private gists" msgstr "" -#: rhodecode/templates/base/base.html:311 +#: kallithea/templates/base/base.html:336 msgid "Search in repositories" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:14 -msgid "Inherit default permissions" -msgstr "继承默认权限" - -#: rhodecode/templates/base/default_perms_box.html:18 +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:19 #, python-format msgid "" -"Select to inherit permissions from %s settings. With this selected below " -"options does not apply." -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:26 +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:28 msgid "Create repositories" msgstr "创建版本库" -#: rhodecode/templates/base/default_perms_box.html:30 +#: kallithea/templates/base/default_perms_box.html:33 msgid "Select this option to allow repository creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:35 +#: kallithea/templates/base/default_perms_box.html:40 msgid "Create user groups" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:39 +#: kallithea/templates/base/default_perms_box.html:45 msgid "Select this option to allow user group creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:44 +#: kallithea/templates/base/default_perms_box.html:52 msgid "Fork repositories" msgstr "复刻版本库" -#: rhodecode/templates/base/default_perms_box.html:48 +#: kallithea/templates/base/default_perms_box.html:57 msgid "Select this option to allow repository forking for this user" msgstr "" -#: rhodecode/templates/base/perms_summary.html:11 +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:22 msgid "No permissions defined yet" msgstr "" -#: rhodecode/templates/base/perms_summary.html:19 -#: rhodecode/templates/base/perms_summary.html:38 +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 msgid "Permission" msgstr "权限" -#: rhodecode/templates/base/perms_summary.html:20 -#: rhodecode/templates/base/perms_summary.html:39 +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 msgid "Edit Permission" msgstr "编辑权限" -#: rhodecode/templates/base/root.html:44 +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 msgid "Add another comment" msgstr "" -#: rhodecode/templates/base/root.html:45 -#: rhodecode/templates/data_table/_dt_elements.html:147 +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 msgid "Stop following this repository" msgstr "停止关注该版本库" -#: rhodecode/templates/base/root.html:46 +#: kallithea/templates/base/root.html:47 msgid "Start following this repository" msgstr "开始关注该版本库" -#: rhodecode/templates/base/root.html:47 +#: kallithea/templates/base/root.html:48 msgid "Group" msgstr "组" -#: rhodecode/templates/base/root.html:48 +#: kallithea/templates/base/root.html:49 msgid "members" msgstr "成员" -#: rhodecode/templates/base/root.html:49 -#: rhodecode/templates/pullrequests/pullrequest.html:203 +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 msgid "Loading ..." msgstr "" -#: rhodecode/templates/base/root.html:50 +#: kallithea/templates/base/root.html:51 +msgid "loading ..." +msgstr "" + +#: kallithea/templates/base/root.html:52 msgid "Search truncated" msgstr "" -#: rhodecode/templates/base/root.html:51 +#: kallithea/templates/base/root.html:53 msgid "No matching files" msgstr "" -#: rhodecode/templates/base/root.html:52 -#: rhodecode/templates/changelog/changelog.html:45 +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 msgid "Open new pull request" msgstr "新建拉取请求" -#: rhodecode/templates/base/root.html:53 +#: kallithea/templates/base/root.html:55 msgid "Open new pull request for selected changesets" msgstr "为选择的变更集创建新的拉取请求" -#: rhodecode/templates/base/root.html:54 +#: kallithea/templates/base/root.html:56 msgid "Show selected changesets __S -> __E" msgstr "" -#: rhodecode/templates/base/root.html:55 +#: kallithea/templates/base/root.html:57 msgid "Show selected changeset __S" msgstr "" -#: rhodecode/templates/base/root.html:56 +#: kallithea/templates/base/root.html:58 msgid "Selection link" msgstr "选择链接" -#: rhodecode/templates/base/root.html:57 -#: rhodecode/templates/changeset/diff_block.html:8 +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 msgid "Collapse diff" msgstr "" -#: rhodecode/templates/base/root.html:58 +#: kallithea/templates/base/root.html:60 msgid "Expand diff" msgstr "" -#: rhodecode/templates/base/root.html:59 +#: kallithea/templates/base/root.html:61 msgid "Failed to revoke permission" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:5 +#: kallithea/templates/base/root.html:62 +msgid "confirm to revoke permission for {0}: {1} ?" +msgstr "" + +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:5 #, python-format msgid "%s Bookmarks" msgstr "%s书签" -#: rhodecode/templates/bookmarks/bookmarks.html:26 -msgid "Compare bookmarks" -msgstr "" - -#: rhodecode/templates/bookmarks/bookmarks.html:51 -#: rhodecode/templates/bookmarks/bookmarks_data.html:8 -#: rhodecode/templates/branches/branches.html:50 -#: rhodecode/templates/branches/branches_data.html:8 -#: rhodecode/templates/changelog/changelog_summary_data.html:8 -#: rhodecode/templates/tags/tags.html:51 -#: rhodecode/templates/tags/tags_data.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 msgid "Author" msgstr "作者" -#: rhodecode/templates/bookmarks/bookmarks.html:52 -#: rhodecode/templates/bookmarks/bookmarks_data.html:9 -#: rhodecode/templates/branches/branches.html:51 -#: rhodecode/templates/branches/branches_data.html:9 -#: rhodecode/templates/changelog/changelog_summary_data.html:5 -#: rhodecode/templates/tags/tags.html:52 -#: rhodecode/templates/tags/tags_data.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 msgid "Revision" msgstr "修订" -#: rhodecode/templates/bookmarks/bookmarks.html:54 -#: rhodecode/templates/bookmarks/bookmarks_data.html:10 -#: rhodecode/templates/branches/branches.html:53 -#: rhodecode/templates/branches/branches_data.html:10 -#: rhodecode/templates/tags/tags.html:54 -#: rhodecode/templates/tags/tags_data.html:10 -msgid "Compare" -msgstr "比较显示" - -#: rhodecode/templates/branches/branches.html:5 +#: kallithea/templates/branches/branches.html:5 #, python-format msgid "%s Branches" msgstr "%s分支" -#: rhodecode/templates/branches/branches.html:26 -msgid "Compare branches" -msgstr "比较分支" - -#: rhodecode/templates/changelog/changelog.html:6 +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 #, python-format msgid "%s Changelog" msgstr "%s修订记录" -#: rhodecode/templates/changelog/changelog.html:19 +#: kallithea/templates/changelog/changelog.html:21 #, python-format msgid "showing %d out of %d revision" msgid_plural "showing %d out of %d revisions" msgstr[0] "显示%d/%d个版本" -#: rhodecode/templates/changelog/changelog.html:39 +#: kallithea/templates/changelog/changelog.html:43 msgid "Clear selection" msgstr "清除选择" -#: rhodecode/templates/changelog/changelog.html:42 -#: rhodecode/templates/forks/forks_data.html:19 +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 #, python-format msgid "Compare fork with %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:42 -msgid "Compare fork with parent" -msgstr "比较复刻和源版本库" - -#: rhodecode/templates/changelog/changelog.html:78 -#: rhodecode/templates/changelog/changelog_summary_data.html:28 -#, python-format -msgid "Click to open associated pull request #%s" -msgstr "点击建立相关的拉取请求 #%s" - -#: rhodecode/templates/changelog/changelog.html:102 -#: rhodecode/templates/summary/summary.html:403 -msgid "Show more" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:115 -#: rhodecode/templates/changelog/changelog_summary_data.html:50 -#: rhodecode/templates/changeset/changeset.html:107 -#: rhodecode/templates/changeset/changeset_range.html:86 +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "显示" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 +#, python-format +msgid "" +"Changeset status: %s\n" +"Click to open associated pull request #%s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 +#, python-format +msgid "Changeset status: %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:114 +msgid "Changeset has comments" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 #, python-format msgid "Bookmark %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:121 -#: rhodecode/templates/changelog/changelog_summary_data.html:56 -#: rhodecode/templates/changeset/changeset.html:113 -#: rhodecode/templates/changeset/changeset_range.html:92 +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 #, python-format msgid "Tag %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:126 -#: rhodecode/templates/changelog/changelog_summary_data.html:61 -#: rhodecode/templates/changeset/changeset.html:117 -#: rhodecode/templates/changeset/changeset_range.html:96 +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 #, python-format msgid "Branch %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:286 +#: kallithea/templates/changelog/changelog.html:299 msgid "There are no changes yet" msgstr "没有任何变更" -#: rhodecode/templates/changelog/changelog_details.html:4 -#: rhodecode/templates/changeset/changeset.html:91 +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 msgid "Removed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:5 -#: rhodecode/templates/changeset/changeset.html:92 +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 msgid "Changed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:6 -#: rhodecode/templates/changeset/changeset.html:93 +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 msgid "Added" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:8 -#: rhodecode/templates/changelog/changelog_details.html:9 -#: rhodecode/templates/changelog/changelog_details.html:10 -#: rhodecode/templates/changeset/changeset.html:95 -#: rhodecode/templates/changeset/changeset.html:96 -#: rhodecode/templates/changeset/changeset.html:97 +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 #, python-format msgid "Affected %s files" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:6 -#: rhodecode/templates/files/files_add.html:75 -#: rhodecode/templates/files/files_edit.html:61 +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 msgid "Commit message" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/changelog/changelog_summary_data.html:7 msgid "Age" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/changelog/changelog_summary_data.html:9 msgid "Refs" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:86 -msgid "Add or upload files directly via RhodeCode" -msgstr "通过RhodeCode直接添加或者上传文件" - -#: rhodecode/templates/changelog/changelog_summary_data.html:89 -#: rhodecode/templates/files/files_add.html:38 -#: rhodecode/templates/files/files_browser.html:31 -msgid "Add new file" -msgstr "新建文件" - -#: rhodecode/templates/changelog/changelog_summary_data.html:95 +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" +msgstr "通过Kallithea直接添加或者上传文件" + +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:95 msgid "Push new repo" msgstr "推送新版本库" -#: rhodecode/templates/changelog/changelog_summary_data.html:103 +#: kallithea/templates/changelog/changelog_summary_data.html:103 msgid "Existing repository?" msgstr "已有版本库?" -#: rhodecode/templates/changeset/changeset.html:6 +#: kallithea/templates/changeset/changeset.html:6 #, python-format msgid "%s Changeset" msgstr "%s修订集" -#: rhodecode/templates/changeset/changeset.html:39 -msgid "No parents" -msgstr "无父版本" - -#: rhodecode/templates/changeset/changeset.html:49 -msgid "No children" -msgstr "无子对象" - -#: rhodecode/templates/changeset/changeset.html:62 -#: rhodecode/templates/changeset/changeset_file_comment.html:20 -#: rhodecode/templates/changeset/changeset_range.html:44 +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 msgid "Changeset status" msgstr "修订集状态" -#: rhodecode/templates/changeset/changeset.html:67 -#: rhodecode/templates/changeset/diff_block.html:22 +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 msgid "Raw diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:68 +#: kallithea/templates/changeset/changeset.html:58 msgid "Patch diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:69 -#: rhodecode/templates/changeset/diff_block.html:23 +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 msgid "Download diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "%d条评论" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "(%d inline)" msgid_plural "(%d inline)" msgstr[0] "(%d内嵌)" -#: rhodecode/templates/changeset/changeset.html:103 -#: rhodecode/templates/changeset/changeset_range.html:82 +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 msgid "merge" msgstr "合并" -#: rhodecode/templates/changeset/changeset.html:126 -#: rhodecode/templates/compare/compare_diff.html:40 -#: rhodecode/templates/pullrequests/pullrequest_show.html:113 +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 #, python-format msgid "%s file changed" msgid_plural "%s files changed" msgstr[0] "修改%s个文件" -#: rhodecode/templates/changeset/changeset.html:128 -#: rhodecode/templates/compare/compare_diff.html:42 -#: rhodecode/templates/pullrequests/pullrequest_show.html:115 +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 #, python-format msgid "%s file changed with %s insertions and %s deletions" msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "修改%s个文件包括%s行插入和%s行删除" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Showing a huge diff might take some time and resources" msgstr "" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Show full diff" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:30 -#, python-format -msgid "Status change on pull request #%s" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:32 +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 +#, python-format +msgid "Vote on pull request #%s" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 #, python-format msgid "Comment on pull request #%s" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:55 +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Status change on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Comment on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:63 msgid "Submitting..." msgstr "提交中……" -#: rhodecode/templates/changeset/changeset_file_comment.html:58 +#: kallithea/templates/changeset/changeset_file_comment.html:66 msgid "Commenting on line {1}." msgstr "在{1}行上评论" -#: rhodecode/templates/changeset/changeset_file_comment.html:59 -#: rhodecode/templates/changeset/changeset_file_comment.html:145 +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 #, python-format msgid "Comments parsed using %s syntax with %s support." msgstr "评论使用%s语法并支持%s" -#: rhodecode/templates/changeset/changeset_file_comment.html:61 -#: rhodecode/templates/changeset/changeset_file_comment.html:147 -msgid "" -"Use @username inside this text to send notification to this RhodeCode user" -msgstr "在文本中使用 @用户名 以发送通知到该RhodeCode用户" - -#: rhodecode/templates/changeset/changeset_file_comment.html:65 -#: rhodecode/templates/changeset/changeset_file_comment.html:152 +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "在文本中使用 @用户名 以发送通知到该Kallithea用户" + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 msgid "Preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:72 -#: rhodecode/templates/changeset/changeset_file_comment.html:170 +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 msgid "Comment preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:80 -#: rhodecode/templates/changeset/changeset_file_comment.html:177 -#: rhodecode/templates/email_templates/changeset_comment.html:16 -#: rhodecode/templates/email_templates/pull_request_comment.html:16 +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 msgid "Comment" msgstr "评论" -#: rhodecode/templates/changeset/changeset_file_comment.html:81 -msgid "Cancel" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "You need to be logged in to comment." msgstr "必须登录才能评论" -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "Login now" msgstr "现在登陆" -#: rhodecode/templates/changeset/changeset_file_comment.html:92 +#: kallithea/templates/changeset/changeset_file_comment.html:100 msgid "Hide" msgstr "隐藏" -#: rhodecode/templates/changeset/changeset_file_comment.html:149 -msgid "Change status" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:179 -msgid "Comment and close" -msgstr "评论并关闭" - -#: rhodecode/templates/changeset/changeset_range.html:5 +#: kallithea/templates/changeset/changeset_file_comment.html:159 +msgid "Vote for pull request status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:161 +msgid "Change changeset status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:179 +msgid "Close (when approved or rejected)" +msgstr "" + +#: kallithea/templates/changeset/changeset_range.html:5 #, python-format msgid "%s Changesets" msgstr "%s修订集" -#: rhodecode/templates/changeset/changeset_range.html:52 +#: kallithea/templates/changeset/changeset_range.html:59 msgid "Files affected" msgstr "影响文件" -#: rhodecode/templates/changeset/diff_block.html:21 +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 msgid "Show full diff for this file" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:29 +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Show full side-by-side diff for this file" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:38 msgid "Show inline comments" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:53 +#: kallithea/templates/changeset/diff_block.html:62 msgid "Show file at latest version in this repo" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:54 +#: kallithea/templates/changeset/diff_block.html:64 msgid "Show file at initial version in this repo" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:4 +#: kallithea/templates/compare/compare_cs.html:4 msgid "No changesets" msgstr "无修订" -#: rhodecode/templates/compare/compare_cs.html:32 +#: kallithea/templates/compare/compare_cs.html:8 msgid "Ancestor" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:5 +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 #, python-format msgid "%s Compare" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:9 +#: kallithea/templates/compare/compare_diff.html:16 msgid "Compare revisions" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:33 -#: rhodecode/templates/pullrequests/pullrequest_show.html:106 +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 #, python-format msgid "Showing %s commit" msgid_plural "Showing %s commits" msgstr[0] "显示%s个提交" -#: rhodecode/templates/compare/compare_diff.html:48 -#: rhodecode/templates/pullrequests/pullrequest_show.html:121 +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 msgid "No files" msgstr "无文件" -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -msgid "confirm to show potentially huge diff" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:54 -#: rhodecode/templates/summary/summary.html:69 +#: kallithea/templates/data_table/_dt_elements.html:63 msgid "Mercurial repository" msgstr "Mercurial版本库" -#: rhodecode/templates/data_table/_dt_elements.html:56 -#: rhodecode/templates/summary/summary.html:72 +#: kallithea/templates/data_table/_dt_elements.html:65 msgid "Git repository" msgstr "Git版本库" -#: rhodecode/templates/data_table/_dt_elements.html:74 -#, python-format -msgid "Fork of %s" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:88 +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "公共版本库" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:96 msgid "No changesets yet" msgstr "无修订" -#: rhodecode/templates/data_table/_dt_elements.html:95 -#: rhodecode/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 #, python-format msgid "Subscribe to %s rss feed" msgstr "订阅%s的RSS" -#: rhodecode/templates/data_table/_dt_elements.html:103 -#: rhodecode/templates/data_table/_dt_elements.html:105 +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 #, python-format msgid "Subscribe to %s atom feed" msgstr "订阅%s的Atom" -#: rhodecode/templates/data_table/_dt_elements.html:122 -#, python-format -msgid "Confirm to delete this repository: %s" -msgstr "确认删除版本库:%s" - -#: rhodecode/templates/data_table/_dt_elements.html:137 -#, python-format -msgid "Confirm to delete this user: %s" -msgstr "确认删除用户:%s" - -#: rhodecode/templates/email_templates/changeset_comment.html:4 -#: rhodecode/templates/email_templates/pull_request.html:4 -#: rhodecode/templates/email_templates/pull_request_comment.html:4 -msgid "URL" -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:6 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:6 #, python-format msgid "%s commented on a %s changeset." msgstr "" -#: rhodecode/templates/email_templates/changeset_comment.html:14 +#: kallithea/templates/email_templates/changeset_comment.html:9 msgid "The changeset status was changed to" msgstr "" -#: rhodecode/templates/email_templates/main.html:8 -msgid "This is a notification from RhodeCode." -msgstr "这是一个RhodeCode通知。" - -#: rhodecode/templates/email_templates/password_reset.html:4 +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." +msgstr "这是一个Kallithea通知。" + +#: kallithea/templates/email_templates/password_reset.html:4 #, python-format msgid "Hello %s" msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:5 +#: kallithea/templates/email_templates/password_reset.html:5 msgid "We received a request to create a new password for your account." msgstr "我们收到重置你用户密码的请求。" -#: rhodecode/templates/email_templates/password_reset.html:6 +#: kallithea/templates/email_templates/password_reset.html:6 msgid "You can generate it by clicking following URL" msgstr "点击下面的链接以重新生成密码:" -#: rhodecode/templates/email_templates/password_reset.html:10 +#: kallithea/templates/email_templates/password_reset.html:10 msgid "Please ignore this email if you did not request a new password ." msgstr "" -#: rhodecode/templates/email_templates/pull_request.html:6 +#: kallithea/templates/email_templates/pull_request.html:6 #, python-format msgid "" -"%s opened a pull request for repository %s and wants you to review changes." -msgstr "" - -#: rhodecode/templates/email_templates/pull_request.html:8 -#: rhodecode/templates/pullrequests/pullrequest.html:34 -#: rhodecode/templates/pullrequests/pullrequest_data.html:14 -#: rhodecode/templates/pullrequests/pullrequest_show.html:25 +"%s opened a pull request for repository %s and wants you to review " +"changes." +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 msgid "Title" msgstr "标题" -#: rhodecode/templates/email_templates/pull_request_comment.html:6 +#: kallithea/templates/email_templates/pull_request_comment.html:6 #, python-format msgid "%s commented on pull request \"%s\"" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:10 +#: kallithea/templates/email_templates/pull_request_comment.html:10 msgid "Pull request was closed with status" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:12 +#: kallithea/templates/email_templates/pull_request_comment.html:12 msgid "Pull request changed status" msgstr "" -#: rhodecode/templates/email_templates/registration.html:6 +#: kallithea/templates/email_templates/registration.html:6 msgid "View this user here" msgstr "查看用户" -#: rhodecode/templates/errors/error_document.html:55 +#: kallithea/templates/errors/error_document.html:47 #, python-format msgid "You will be redirected to %s in %s seconds" msgstr "重定向到%s,于%s秒后" -#: rhodecode/templates/files/file_diff.html:4 -#, python-format -msgid "%s File Diff" -msgstr "" - -#: rhodecode/templates/files/file_diff.html:8 +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 msgid "File diff" msgstr "文件差异" -#: rhodecode/templates/files/files.html:4 -#: rhodecode/templates/files/files.html:76 +#: kallithea/templates/files/diff_2way.html:58 +msgid "ignore white space" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:59 +msgid "turn on edit mode" +msgstr "" + +#: kallithea/templates/files/file_diff.html:4 +#, python-format +msgid "%s File Diff" +msgstr "" + +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 #, python-format msgid "%s Files" msgstr "" -#: rhodecode/templates/files/files.html:30 -#: rhodecode/templates/files/files_add.html:31 -#: rhodecode/templates/files/files_edit.html:31 -msgid "Branch" -msgstr "" - -#: rhodecode/templates/files/files_add.html:4 +#: kallithea/templates/files/files_add.html:4 #, python-format msgid "%s Files Add" msgstr "" -#: rhodecode/templates/files/files_add.html:19 -msgid "Add file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:43 -msgid "File Name" -msgstr "文件名" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:56 +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" +msgstr "新建文件" + +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 +msgid "Location" +msgstr "位置" + +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 msgid "or" msgstr "或者" -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:52 -msgid "Upload file" -msgstr "上传文件" - -#: rhodecode/templates/files/files_add.html:56 -msgid "Create new file" -msgstr "创建新文件" - -#: rhodecode/templates/files/files_add.html:61 -#: rhodecode/templates/files/files_edit.html:37 -#: rhodecode/templates/files/files_ypjax.html:3 -msgid "Location" -msgstr "位置" - -#: rhodecode/templates/files/files_add.html:65 -msgid "use / to separate directories" -msgstr "使用 / 目录分隔符" - -#: rhodecode/templates/files/files_add.html:79 -#: rhodecode/templates/files/files_edit.html:65 +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:58 +msgid "New file mode" +msgstr "" + +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 msgid "Commit changes" msgstr "提交修改" -#: rhodecode/templates/files/files_browser.html:13 -msgid "View" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:14 +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:14 msgid "Previous revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:16 +#: kallithea/templates/files/files_browser.html:16 msgid "Next revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:23 +#: kallithea/templates/files/files_browser.html:22 msgid "Follow current branch" msgstr "" -#: rhodecode/templates/files/files_browser.html:27 -msgid "Search file list" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:35 +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:29 msgid "Loading file list..." msgstr "加载文件列表..." -#: rhodecode/templates/files/files_browser.html:48 +#: kallithea/templates/files/files_browser.html:42 msgid "Size" msgstr "大小" -#: rhodecode/templates/files/files_browser.html:49 +#: kallithea/templates/files/files_browser.html:43 msgid "Mimetype" msgstr "MIME类型" -#: rhodecode/templates/files/files_browser.html:50 +#: kallithea/templates/files/files_browser.html:44 msgid "Last Revision" msgstr "最后修订号" -#: rhodecode/templates/files/files_browser.html:51 +#: kallithea/templates/files/files_browser.html:45 msgid "Last modified" msgstr "最后修改于" -#: rhodecode/templates/files/files_browser.html:52 +#: kallithea/templates/files/files_browser.html:46 msgid "Last committer" msgstr "最后提交者" -#: rhodecode/templates/files/files_edit.html:4 -#, python-format -msgid "%s Files Edit" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:19 +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:25 msgid "Edit file" msgstr "" -#: rhodecode/templates/files/files_edit.html:47 -#: rhodecode/templates/files/files_source.html:23 -msgid "Show annotation" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:49 -#: rhodecode/templates/files/files_source.html:26 -msgid "Download as raw" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:52 +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:58 msgid "Source" msgstr "" -#: rhodecode/templates/files/files_edit.html:57 +#: kallithea/templates/files/files_edit.html:63 msgid "Editing file" msgstr "编辑文件" -#: rhodecode/templates/files/files_history_box.html:2 -msgid "History" -msgstr "历史" - -#: rhodecode/templates/files/files_history_box.html:9 -msgid "Diff to revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:10 -msgid "Show at revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:11 -msgid "Show full history" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:16 +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 #, python-format msgid "%s author" msgid_plural "%s authors" msgstr[0] "%s个作者" -#: rhodecode/templates/files/files_source.html:6 -msgid "Load file history" -msgstr "加载文件历史记录..." - -#: rhodecode/templates/files/files_source.html:21 -msgid "Show source" -msgstr "" - -#: rhodecode/templates/files/files_source.html:29 -#, python-format -msgid "Edit on branch:%s" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 -msgid "Edit on branch:?" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:8 +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:11 +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" +msgstr "" + +#: kallithea/templates/files/files_source.html:38 +#, python-format +msgid "Edit on Branch:%s" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "" + +#: kallithea/templates/files/files_source.html:44 msgid "Editing files allowed only when on branch head revision" msgstr "" -#: rhodecode/templates/files/files_source.html:46 +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:61 #, python-format msgid "Binary file (%s)" msgstr "二进制文件(%s)" -#: rhodecode/templates/files/files_source.html:55 +#: kallithea/templates/files/files_source.html:71 msgid "File is too big to display" msgstr "文件过大,不能显示" -#: rhodecode/templates/files/files_ypjax.html:5 +#: kallithea/templates/files/files_ypjax.html:5 msgid "annotation" msgstr "显示注释" -#: rhodecode/templates/files/files_ypjax.html:15 -msgid "Go back" -msgstr "返回" - -#: rhodecode/templates/files/files_ypjax.html:16 +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:24 msgid "No files at given path" msgstr "指定的路径中没有文件" -#: rhodecode/templates/followers/followers.html:5 +#: kallithea/templates/followers/followers.html:5 #, python-format msgid "%s Followers" msgstr "%s个关注者" -#: rhodecode/templates/followers/followers.html:9 -#: rhodecode/templates/summary/summary.html:183 -#: rhodecode/templates/summary/summary.html:184 +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 msgid "Followers" msgstr "关注者" -#: rhodecode/templates/followers/followers_data.html:12 +#: kallithea/templates/followers/followers_data.html:12 msgid "Started following -" msgstr "开始关注 - " -#: rhodecode/templates/forks/fork.html:5 -#, python-format -msgid "%s Fork" -msgstr "%s的复刻" - -#: rhodecode/templates/forks/fork.html:28 +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:30 msgid "Fork name" msgstr "复刻名称" -#: rhodecode/templates/forks/fork.html:65 +#: kallithea/templates/forks/fork.html:71 msgid "Private" msgstr "私有" -#: rhodecode/templates/forks/fork.html:74 +#: kallithea/templates/forks/fork.html:80 msgid "Copy permissions" msgstr "拷贝权限" -#: rhodecode/templates/forks/fork.html:78 +#: kallithea/templates/forks/fork.html:84 msgid "Copy permissions from forked repository" msgstr "从被复刻版本库拷贝权限" -#: rhodecode/templates/forks/fork.html:84 +#: kallithea/templates/forks/fork.html:90 msgid "Update after clone" msgstr "克隆后更新" -#: rhodecode/templates/forks/fork.html:88 +#: kallithea/templates/forks/fork.html:94 msgid "Checkout source after making a clone" msgstr "完成克隆后检出源代码" -#: rhodecode/templates/forks/fork.html:93 -msgid "Fork this repository" -msgstr "" - -#: rhodecode/templates/forks/forks.html:5 +#: kallithea/templates/forks/fork.html:99 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 #, python-format msgid "%s Forks" msgstr "%s个复刻" -#: rhodecode/templates/forks/forks.html:9 -#: rhodecode/templates/summary/summary.html:189 -#: rhodecode/templates/summary/summary.html:190 +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 msgid "Forks" msgstr "复刻" -#: rhodecode/templates/forks/forks_data.html:17 +#: kallithea/templates/forks/forks_data.html:17 msgid "Forked" msgstr "" -#: rhodecode/templates/forks/forks_data.html:42 +#: kallithea/templates/forks/forks_data.html:42 msgid "There are no forks yet" msgstr "无复刻" -#: rhodecode/templates/journal/journal.html:21 +#: kallithea/templates/journal/journal.html:24 msgid "ATOM journal feed" msgstr "订阅日志ATOM" -#: rhodecode/templates/journal/journal.html:22 +#: kallithea/templates/journal/journal.html:25 msgid "RSS journal feed" msgstr "订阅日志RSS" -#: rhodecode/templates/journal/journal.html:32 -msgid "Refresh" -msgstr "刷新" - -#: rhodecode/templates/journal/journal.html:35 -#: rhodecode/templates/journal/public_journal.html:24 -msgid "ATOM feed" -msgstr "订阅ATOM" - -#: rhodecode/templates/journal/journal.html:51 -msgid "Watched" -msgstr "关注的" - -#: rhodecode/templates/journal/journal_data.html:55 +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "我的版本库" + +#: kallithea/templates/journal/journal_data.html:55 msgid "No entries yet" msgstr "没有条目" -#: rhodecode/templates/journal/public_journal.html:4 -#: rhodecode/templates/journal/public_journal.html:21 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 msgid "Public Journal" msgstr "公共日志" -#: rhodecode/templates/journal/public_journal.html:13 +#: kallithea/templates/journal/public_journal.html:16 msgid "ATOM public journal feed" msgstr "订阅公共日志ATOM" -#: rhodecode/templates/journal/public_journal.html:14 +#: kallithea/templates/journal/public_journal.html:17 msgid "RSS public journal feed" msgstr "订阅公共日志RSS" -#: rhodecode/templates/pullrequests/pullrequest.html:4 -#: rhodecode/templates/pullrequests/pullrequest.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 msgid "New pull request" msgstr "新建拉取请求" -#: rhodecode/templates/pullrequests/pullrequest.html:25 -msgid "Create new pull request" -msgstr "创建新的拉取请求" - -#: rhodecode/templates/pullrequests/pullrequest.html:47 +#: kallithea/templates/pullrequests/pullrequest.html:44 msgid "Write a short description on this pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:53 +#: kallithea/templates/pullrequests/pullrequest.html:50 msgid "Changeset flow" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:60 -#: rhodecode/templates/pullrequests/pullrequest_show.html:65 +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 msgid "Origin repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:85 -msgid "Send pull request" -msgstr "发送拉取请求" - -#: rhodecode/templates/pullrequests/pullrequest.html:94 -#: rhodecode/templates/pullrequests/pullrequest_show.html:137 +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 msgid "Pull request reviewers" msgstr "拉取请求检视人员" -#: rhodecode/templates/pullrequests/pullrequest.html:103 -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 msgid "owner" msgstr "所有者" -#: rhodecode/templates/pullrequests/pullrequest.html:115 +#: kallithea/templates/pullrequests/pullrequest.html:114 msgid "Add reviewer to this pull request." msgstr "为这个拉取请求增加检视人员" -#: rhodecode/templates/pullrequests/pullrequest.html:129 +#: kallithea/templates/pullrequests/pullrequest.html:128 msgid "Detailed compare view" msgstr "详细比较显示" -#: rhodecode/templates/pullrequests/pullrequest.html:150 +#: kallithea/templates/pullrequests/pullrequest.html:149 msgid "Destination repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:4 +#: kallithea/templates/pullrequests/pullrequest_show.html:4 #, python-format msgid "%s Pull Request #%s" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:35 +#: kallithea/templates/pullrequests/pullrequest_show.html:36 msgid "Review status" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:40 -msgid "Pull request status" -msgstr "拉取请求状态" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 +msgid "Pull request status calculated from votes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:56 msgid "Still not reviewed by" msgstr "还未检视的检视人员" -#: rhodecode/templates/pullrequests/pullrequest_show.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:60 #, python-format msgid "%d reviewer" msgid_plural "%d reviewers" msgstr[0] "%d个检视者" -#: rhodecode/templates/pullrequests/pullrequest_show.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:62 msgid "Pull request was reviewed by all reviewers" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:89 -msgid "Created on" -msgstr "创建于" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:102 +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 +msgid "Pull changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "reviewer" +msgstr "检视者" + +#: kallithea/templates/pullrequests/pullrequest_show.html:133 +msgid "Add or remove reviewer to this pull request." +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:137 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 msgid "Compare view" msgstr "比较显示" -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 -msgid "reviewer" -msgstr "检视者" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:164 -msgid "Add or remove reviewer to this pull request." -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:168 -msgid "Save changes" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:4 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 #, python-format msgid "%s Pull Requests" msgstr "" -#: rhodecode/templates/search/search.html:6 -msgid "Search repository" -msgstr "" - -#: rhodecode/templates/search/search.html:8 -#: rhodecode/templates/search/search.html:16 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 +#, python-format +msgid "Pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 +#, python-format +msgid "Pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 +msgid "Hide closed pull requests" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 +msgid "Show closed pull requests too" +msgstr "" + +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 msgid "Search in all repositories" msgstr "在所有的版本库中搜索" -#: rhodecode/templates/search/search.html:50 +#: kallithea/templates/search/search.html:53 msgid "Search term" msgstr "搜索短语" -#: rhodecode/templates/search/search.html:62 +#: kallithea/templates/search/search.html:65 msgid "Search in" msgstr "搜索范围" -#: rhodecode/templates/search/search.html:65 +#: kallithea/templates/search/search.html:68 msgid "File contents" msgstr "文件内容" -#: rhodecode/templates/search/search.html:66 +#: kallithea/templates/search/search.html:69 msgid "Commit messages" msgstr "提交信息" -#: rhodecode/templates/search/search.html:67 +#: kallithea/templates/search/search.html:70 msgid "File names" msgstr "文件名" -#: rhodecode/templates/search/search_commit.html:35 -#: rhodecode/templates/search/search_content.html:21 -#: rhodecode/templates/search/search_path.html:15 +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 msgid "Permission denied" msgstr "权限不足" -#: rhodecode/templates/summary/summary.html:4 +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 +#, python-format +msgid "%s ATOM feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 +#, python-format +msgid "%s RSS feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "已收集的统计:" + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "文件" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "提交" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "文件已添加" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "文件已更改" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "文件已删除" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "提交" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "文件已添加" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "文件已更改" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "文件已删除" + +#: kallithea/templates/summary/summary.html:4 #, python-format msgid "%s Summary" msgstr "%s概要" -#: rhodecode/templates/summary/summary.html:16 -#, python-format -msgid "%s ATOM feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:17 -#, python-format -msgid "%s RSS feed" -msgstr "" - -#: rhodecode/templates/summary/summary.html:62 +#: kallithea/templates/summary/summary.html:16 #, python-format msgid "Repository locked by %s" msgstr "版本库由%s锁定" -#: rhodecode/templates/summary/summary.html:64 +#: kallithea/templates/summary/summary.html:18 msgid "Repository unlocked" msgstr "版本库未锁定" -#: rhodecode/templates/summary/summary.html:83 -#, python-format -msgid "Non changable ID %s" -msgstr "不可变ID %s" - -#: rhodecode/templates/summary/summary.html:88 -msgid "Public" -msgstr "" - -#: rhodecode/templates/summary/summary.html:88 -#: rhodecode/templates/summary/summary.html:89 -msgid "Fork of" -msgstr "复刻自" - -#: rhodecode/templates/summary/summary.html:97 -msgid "Remote clone" -msgstr "" - -#: rhodecode/templates/summary/summary.html:117 -msgid "Contact" -msgstr "联系方式" - -#: rhodecode/templates/summary/summary.html:131 +#: kallithea/templates/summary/summary.html:76 msgid "Clone url" msgstr "克隆地址" -#: rhodecode/templates/summary/summary.html:136 +#: kallithea/templates/summary/summary.html:81 msgid "Show by Name" msgstr "以名字显示" -#: rhodecode/templates/summary/summary.html:137 +#: kallithea/templates/summary/summary.html:82 msgid "Show by ID" msgstr "按ID显示" -#: rhodecode/templates/summary/summary.html:143 +#: kallithea/templates/summary/summary.html:99 msgid "Trending files" msgstr "文件趋势图" -#: rhodecode/templates/summary/summary.html:151 -#: rhodecode/templates/summary/summary.html:167 -msgid "Enable" -msgstr "" - -#: rhodecode/templates/summary/summary.html:159 +#: kallithea/templates/summary/summary.html:115 msgid "Download" msgstr "下载" -#: rhodecode/templates/summary/summary.html:163 +#: kallithea/templates/summary/summary.html:119 msgid "There are no downloads yet" msgstr "无下载" -#: rhodecode/templates/summary/summary.html:165 +#: kallithea/templates/summary/summary.html:121 msgid "Downloads are disabled for this repository" msgstr "这个版本库的下载已经禁用" -#: rhodecode/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:127 msgid "Download as zip" msgstr "zip打包下载" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "Check this to download archive with subrepos" msgstr "勾选以下载包含子版本库的压缩包" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "with subrepos" msgstr "包括子版本库" -#: rhodecode/templates/summary/summary.html:197 +#: kallithea/templates/summary/summary.html:163 msgid "Repository Size" msgstr "" -#: rhodecode/templates/summary/summary.html:204 -#: rhodecode/templates/summary/summary.html:206 +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 msgid "Feed" msgstr "" -#: rhodecode/templates/summary/summary.html:224 -msgid "Commit activity by day / author" -msgstr "按日期或作者的提交活动" - -#: rhodecode/templates/summary/summary.html:232 -msgid "enable" -msgstr "启用" - -#: rhodecode/templates/summary/summary.html:235 -msgid "Stats gathered: " -msgstr "已收集的统计:" - -#: rhodecode/templates/summary/summary.html:256 +#: kallithea/templates/summary/summary.html:193 msgid "Latest changes" msgstr "" -#: rhodecode/templates/summary/summary.html:258 +#: kallithea/templates/summary/summary.html:195 msgid "Quick start" msgstr "快速入门" -#: rhodecode/templates/summary/summary.html:272 -#, python-format -msgid "Readme file from revision %s" -msgstr "" - -#: rhodecode/templates/summary/summary.html:332 +#: kallithea/templates/summary/summary.html:209 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:299 #, python-format msgid "Download %s as %s" msgstr "下载%s为%s包" -#: rhodecode/templates/summary/summary.html:379 -msgid "files" -msgstr "文件" - -#: rhodecode/templates/summary/summary.html:689 -msgid "commits" -msgstr "提交" - -#: rhodecode/templates/summary/summary.html:690 -msgid "files added" -msgstr "文件已添加" - -#: rhodecode/templates/summary/summary.html:691 -msgid "files changed" -msgstr "文件已更改" - -#: rhodecode/templates/summary/summary.html:692 -msgid "files removed" -msgstr "文件已删除" - -#: rhodecode/templates/summary/summary.html:694 -msgid "commit" -msgstr "提交" - -#: rhodecode/templates/summary/summary.html:695 -msgid "file added" -msgstr "文件已添加" - -#: rhodecode/templates/summary/summary.html:696 -msgid "file changed" -msgstr "文件已更改" - -#: rhodecode/templates/summary/summary.html:697 -msgid "file removed" -msgstr "文件已删除" - -#: rhodecode/templates/tags/tags.html:5 +#: kallithea/templates/tags/tags.html:5 #, python-format msgid "%s Tags" msgstr "%s标签" -#: rhodecode/templates/tags/tags.html:26 +#: kallithea/templates/tags/tags.html:29 msgid "Compare tags" msgstr "比较标签" + diff --git a/rhodecode/i18n/zh_TW/LC_MESSAGES/rhodecode.mo b/kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.mo rename from rhodecode/i18n/zh_TW/LC_MESSAGES/rhodecode.mo rename to kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.mo index 4a8dd82789882d142b68b69b946c872cf11cb6e0..ca15dbaaae573232a4b016a18f5db507528d4072 GIT binary patch literal 77389 zc%1EB2Yl4U@;@tz1qC~n6Ge!SfaU2EpCVEu6p18&iinrHUy>u2yLcrb6r~e7JgI^- zL7Ma`9es8zSP<+bm!bkvETHIrX20`mmkY)A^!>w!-2Arh&d$!x&d%a#64*GY~ z$qvV*1h-!4u>I@R)ZsXjU~hu;2o5EfL~s?sS_Gp6>k~Y!8Q?z%au(?X?<6>Y-~|L< zBzQK#j|rYba2LVz2>wj4I>8#v9gd3#Ueg@@jhiE08o{arwdSZtuE5>|&*1uqd%VCW z37$o8iKN@u9Ob_(;hzfJMet&RhX|fV@VplAzl>ltg4c?>Q456MMX(0JloqI$rv=K7 z5WI|F-xk2%G=irST;Brqc%cRA@eaW%1V15oD!~#7-`xW3{fXce1kb$-_`B{d;3f4g zl$$}&Nw5dOEP|8oLVhQ=bU0cQJd@x=g7>yWd-n=FEgAK_g5ZS&8z!SYEye#Hf~RnQ zC8J(h$;da5jCSNp{JsRwWqc>2pQcEfkyKxf|&yq5c`HPW?gjr=;b23`6Ho=oUGlk6;Q75&^lw=z#@)}UD8FhN%Bh(K|EtqbPD6qx^Y~3ezKzAd zg~U%u!}z+7;MGho;y)%0bnv*OTO)8&8rty!!RxplX~0X(4xrCg9Z;Y49ncB_3`1`3N_)hIk#6uV#oiJ_&bVB`>c0#*f?u7BVyOZ!^ao4yP_`m92#J~Ms)UP8! z%GwdQ7x}+%FY3EZ;0O1De?{*F-m2V({LUswL)LNmeKJ1o!??;Ln9KFL5BT`@KGfqd z!I}iC-;eZ3_e(wQM?ZBW*pOh?`+=v?0;dUFBL!qo216{GOnf>Hh)HQ$K=N5uE-2#^rwm ze)$0S{yAMR-WzrS-aB%s;PV0(@bfPh%6rfSI?Qw-Kfep*^>ATa4R!&KQ(dUfI`Q8s?k`+u{{a`; zStT9ytDTN^{e$2?3ARp0{sYpHesnt0&q+slYtlha&r7=ZBz#vo>iKgz=(~y=?kn7g zU)PQD8VPLW#<;oPjd>u;jru)Cuz=uGZs5!50X}PckgkCT;c`5 z^q{_r3Es^8=fOO9z=LuRN%(0R@Or+6c3dj%L=F9Lqxj#i0dLtF=wpZm`DM1mJ39m8 z^~Ma;r)dV}r4AXOw?{Kj|G^ok-vok*jL!_zyI9hllnHo#CdN~pOoZQ+De_t-`XwU% z!!t2&&dWr3pJZa3pPmK(Te2`-0|Fn*0=`#gVO)Nmh4FQU7xU^3Uev2A!5avU@FIMR z_?HR1up7dgcSAV^-M~i{cSHaDryJ<#{cdP~aW}MkcQ@d@S~ld?OS2LGrflG~O*Z;H zD;xcklZ}4vnGJq2FdO4`dN%OBARGOMBhjM`5U=HdrBnRyunS=PNa?qa5If(yK4(Rs%9JGH|4$3*vkNTeONByq$Bi*%r z^yBq@jE|;%;Hiy--|I)Y5BZUw<_8{n5F`?D6iR-3{AlmDew24|K>9I&d~OJ!owpMF z?nL5q0i=p}J~ng{wiH6Qh;l@B~M$Va@J^O3$?KJxeEW1i2;hdjK6U=xDR z=c8U#x}zPJbVoa#-O-QNbq79g>khoM?2i6x-yQw+kc0=szejiAw@|{zhw0oZ9 zyQw?s_o}4-RN{Tr9dgrw?&yyj3czRnS%7|QSs?PgxLpNke^vq7A1MI6_ZB#|0QFu_ zfbv%s0DrF%q^Z@hmtbRpDLqjC(LH3|>4Es`dLZ9zJy74B0(bX7xhM5Rz0c_hzHza@ zc0JLqfjv?F=$^pq<2_~Gm+*Bxfu|QF{9OqzmVCeK2|WDL6LQ|ky)chn)(hc{djX#< zdjT(Ly-@FrUT9CRUdV5#xF7F@^5*tJ{a5z_{r{&I%Kuo>?~(YY^hP-~dL!MXy}|eD z5xkt~v^Uz3-5c|NUT>ru+8gzmDB<&agU(h;J}>n~z2B4kzvzwr`nosjand75f8HaA zf6XJP=RY1n{n|YOexymfK93;%zr{W85#VjzBWUO5M^LZV2;M~SgGbP>)gMK9mpqE_ zdIV{y=eUJn3e)kUn74L5igFJ=ius~iALM%*!G95KMes&~gZrTW*Y`pG`}&|hhx(wM zXZFRoJ-;u;+jV`h4!yZA!iV=od&l)fd9(TguWJc5BKUe=wDa_Sz^k*L)LY!Q^h0^g z`T@Tk`vFhs{g8j}exTn${lF(C_rpB9T;hGy5B%qcei&c3^ar1~qd(mJ`lDS#`lFmN z;(k)#g8snE^8VA7IUN8XZHx59(Ul@RV-WmY9|6~C0 z@`J!C1Cjp)13`}s2O__F1_B@Mfk^-GK#Z412BM#*4}{#XbRguPcL$Lytr`qEeswVD@J(@lBk{i-40@|l2)XdKLbN+lhkEaTpVtb}o*jjthp#1ll_98awINs!)fs~J-aQ26bsK{E zoG=9ZVTJg=E%EmcLA|OC1*|<3dX!s-qCfHljvI>lEGKvi(*;2v_y16=H?(1Zg~QOl z3x;7m_S!JuZQn59r^;~j!^Oi<|AgU4*JL=_=^2jtb|=`9%N>q-eoXK#9=F3GN8ULC zbm||0@V+B}pC?8DpKC^--Y<)P$q3|o;z;m?D@GzbZ6xXy90|G|FcS1OdnD+5{YcdF z-I2iau91*y&l`ny-8Kq%Z9fX>9v+2u6plhUQ$`{EHi=h8kftifX`>OZ|7g(XgwfzX zvqz);3nYB~XpE~jCEk~#K{r1TY(emZF(L@i*d59OrP* zlH8F!4&(6Uaj3_Rap;GS#sOb@#-ZI+#-pFF91nclI3Ds+%kj`FwIN8NiKFLu;N`%0 zq(3|!dXMubApaHK1hjAe1dNB1 zC(3$bqO3P2g060w2!53|5%luNMA6$$1RbuD@V6(59%mx(TYVDhb?GF~TavgtOoE)0 zISKq_#3b~?bCW=)A5TI)-%rB$KJ#&mi~5hF9W5V6y?u{kT=sq(^X^Q7%?a*&9DL=9 z$$)hxgB}_Pylpb@-+D6e*>y7L!!sHAW=pzWlTrQvi9c&H=z7g$*=LxH@%yr*`&Qze zItA^yWQynureM6Zo&tP!n}T{2P63|BPeHqvOaVS$7Faw5{O6=65U=(Vs88c3(C)5J zAbh|R$p5J)kpJ^ffL^|M0_`|&D&VD4(cY`4qJI*mf(~w&3OZ~&6?kYW@mftqdF`e` z&k&dj{FhAyot-reeC+CJkpF$t5P$VF$iMGR10HUgj{4s-9qr7Xj{Y1l9pTdjuA7d0 zw+q}g9r!zW2Ke+PGtlm|8PLBJ%s{^{n*sVNn}Ph#nThpZ!c5>{^h}JeEd-bF_$Anh z;EX3BZykIR?XNQn{abGq==-`^sK*_%Fm5}Ef45n{Pr)qU`;l2lKV=s1I(-)8y!o?$ zkAt%?t}dR9aed8f(07B`pqFN|f%ki7i+)DpJuKlpW}}}*&PF{RpN(<2Q1aP68}#zk zY|zzdPa)j}PXW)@J_Y%s#Z$m%-cz8L;o@HK6!PEl6#DVCr_di4%|ZGb<{KC4i`WMaxo}ZBL6?2i_*14$1 zj=7+p{d0krv*rO_Fc1BH#XQhOi+PxTvk4Aie9c3DUNj%&Ts|M}8|I_GZkdn%yN%$( z1Ut`1y$k-Eh~^u@(S69S^+w}Zw2^B zFG<&T1?XdlxK|6@B>BI%Le?z;KUsl#e!T+i*tY`s`B~tZD^czxE0NEYE0Hc?CHTip zE5T2?u0%dT3GcoV<7(ha;N|I+nBO*v`whwOGjW%#M7w@mDRRUr)Ti1i#H+aq`CqjP zcu81=bcy2Mcoot&Uj@3ldll&V-c_j2@KwOmq*cg&DnSzK9P=do(^B3tac^9OcKv6S z=s8!3-b3>FZWZwIqrekaqny)Mqh1%RMm}{{qh3h@Z(fc1-LV?!TCGNY_pF9o*iq6y zwi@%(Y>EG|_?NCm{SOiB#`L>}Xp&&=8q|OP8r1WbH7LK@GpPUh&&a&}4Ei1zxuS{N?ry zDF0sZcWnTk{NjE@!iQ}D-x#|A^g4F~%712q$VD5#hrZZ=`a3qF9#uD@9v5vyd#>6D zJk*o$>o-cjZv>xfwGsI1wh?qTd?U)Awh{H3yAkxeM)Lc5BkVN}Y{dTm9h=bJodUnv zg!)$5jQU=*8Tnnk8UBfz(ciakM!lMCM!u~#qh6^JzsqLOS;l7Y`RR>tphNPqfs zX#d5}p}zIRedBXzXA6O?ohv^q1p#^uwg*VXra& zdCYGozaZ^07R3GrLLgz+4F3F&6MgmJs=CFFnJ%LxD1%Od~0jP{Rw8SR|#GTJ#y;FgymSA8t; z4obQcUy=R8SI`d)UIG4Ze+6<`hgX2_oL4Y^gkKRo#Vf%7npe=jFTDaf{^%8%A6}99 zLHtjC73G}sD)`zZuOi(_$uhL?pE|;!>wpfldWjyeOsX~$=VA14A~00d}=Gwt=|ef{zv?`ZACpxB>mp4 zz?0)OjE4(fLpk+c13v!s8ulITc@6d&qhAC5-hU1CKIwJXYgBz5GG0LOe}i@GZoD^exnL>|5yP zB?7m-1wOs+Ezr|7Z)1Ji>}`z8EP*562H#)tHu8DrZQ%Wzx6zMhyaWFm-vRxlyaW7( z-a$Rby@ULhy#u;@^BuJB#CI`%YrG3Q+$ym3yP%`a?}GjV;_mk@#?N?(H&fs;iTCWg zz~j5`fzlZfom-m3r$?pmMy(jxK?;-uy?};4r9@78v9>&#~ zJAlWlcA!3Y?12A0;?CNE_806xJBRN;{pRmLyVmZ2Joe@elymw{q(5gT(%0FE^8UFK z^wfMO(sh#XoSjJb$WDxhf#QBl!XMu$`)&f)NxWBgqMbW;qJBT_gdXMW_rdoH-v>TN zyf5S6eUv*#{5QOh`n>o)+Q0LC(Cv5cqrMk@fOXr|AHe;<2PoGo?)(o>&jBAG|6$^u z{DJKIO1zgoko}4eM34Rf>@})=huFm5cAU750PKdhsgh{4^h7#Kg2rb z(vMK@Rv)1qnF0$w!gv}c;R`+j9$)%M-0zj}+MmL|t-zk2B7EMbDCeV3!AEL*hW@Gh z8R+!(&%_S!Gqk(?XTVSBGsvxdJ`?)*40v7e8T$Q2iMLhYPRX}e+&_H=yr2F#@Y~>X z;Qyx2VXx8rbI398d=5IXyqNgeX|La-=Iju(##&Mq_w0DTOA1{*iwdA|F2<=}j`K>QP zy|xuWU-yaR*CGo4Hc^y!e-!m}MP+|5Dt0MR*lWy@cvDM(x7nrOSFe_$UE526k1t9Q zZ&xY$=Rhgyd3G7NelN zUSq*GXxCTYp#Kg^{0sIX-}-xj&l~n)Jhj{_{C6+f=iLjw5fnIA!av@N^1s?E`vrT^ zo>TWB{DOVJ(^dP#?r9&wo9;utsryj=1N$K7x%Xjy=_TP)_W_@C_5m-;_o3d;??Zb& zko?NTeNf7)vLE%jU_a>JxgX^>+K=?D_anY*Kk6CSk958EgYOO74?Wz|68@^B+ac+8 zi~Fbj=-=uGKrfdaKt2r*px%uSpdGCbU>-<2Ap0=~(4Jlrf8+tw^N9nR0Dm)a%A?p$EP5Tkw^FZ&6-f3IF%E(Bn`47WNu@zQw$C$9E|A zq3~VxgD!i1FZz`4u@0Rf@xS{X z?LGWG$~*H1vCsVh{Nbh_(4Vd!fY*nA5W5_45B&l48utV8no>0iJfUKan-Uu1rCoS^cpNl@9d z5M(_{6N20yy#-Dt$oW1)koN(fBgpm|hY51OcRS$(weA=|ko$KIL3Pf7pt7eUsO*JL zL^5$SFd|Az>2eRB!2y~YTF+^+2ed7pD1L6##Mopge#f5u4&FCfU{W!y=~ zXUR#Z_h#|`_$1_ekRbDg3ryuG0FF~f;o&=fRrVwO0Uw$&`xs@Q}xrm@zZ=Qm7 z-AIt}ntTeJ&)!Cqz@Y!hZ6K8`CpO)~K&juasKO6maS~b+GdNt77)#7eVkmaN<1ew3|uZDhj zrW)w;yD->&U4U?f1QJRKXeZAdzc{4yZs5Wy~f&efG5YffK|=~ot!Q3 z(sP0TYbE@4fz8iFzHJCHU+Qu$%GD%(UxF;hj+6M439|e=Q_{U6@jf^g?b&lK_)*pB zQvd2`&%dgp9`{!V9<#)qUmf%@usZNMu{!wA%IfHk_Xsk-+gly{=-e6zzo`bsM= zI@^36_}F^{S^mG`e6+V4L6(2}oDV#Faz5I1NW#y$0Qk7-0{Az+0P)&ifPT-p0QvWm z@JR$&Zh!g$wD&85tbaM{LiBr!3qfDKFGRkx2=e-G^M$}eor^HO?j^|f8iNV4y~aN; zK0(P_qc2ALH(reXefDDX%S#ud9`9X@dh8be6D|RM&bb8mzVH&H|Hmc3>n#LX&TD!J z@b~XaFs_yn=JkN+GxjZwNa0bwb7pgY9s&YwNd`FwLyoUiU0oE;H&3fbAqzh z=zI*|6YH`PV^Ua1Q@`%v7a5`L&I z_`oR%po236R!_hs|}`ZXobZfgL0~>ssU!kaYRiVjdqL@fKc-_HLH& z7p}#)dRxK|U5j>{RS)!YSv}-?Q$67AHgUJB2RwAF2fVt(KSyA=9`Mpr(mh%a<&LQb zyiBNv{+eD7bUeQv>hrOr`%3cPLy+w?4oUjMQr=1R;jUI+gASvBK1+Po&pC*{1F1j*2jE0xjy*FbV$v|AZvLa}v^BmW2A(NkTa{C4v5LO+q`82|AoEzsFfSoE*&`);!LD-|5bB`7^bU7IwPA&f0bJvowD~sDik;5ueW))EGY32WvTJOlo4mhqvyP#rC3{Z;`X%^mQ2%rE6xpt*uNB##jHa)zdP__Ik`yS9eo z&OjhL#}&+0k?st-{O&AGeK%Dd?+av_4x$2^1Mvbmxh^Ij`V4BWu-BhS^~()}yx~Bw zfW2FIeVVhGHzUJvH1~MJh9l(lXo=|si42_{OSF*j;cVjZn2u(ePYbI8TLgT*0Pw&L zX+;Y6SbL+#%K0ge_Nl1`4%!>lb!G+wkzDGmP*!@t6^tKBE$3FMY*Goo?kx2crnZN| zUN`(BIfPZ!{4^J$x-tU_V94pNNH{AHG{00#+n{oBY-1EAl?%7gXRX?yT6zp`SYiMJ zlmPYN4=<3L!T3ks9^D;^_0ZkUd>UI^8Lyv43lC$XF&^#__9&Ohu_gisGDg44-mHv3 z&_YvA!D778Du_~OvZU~aoc;g}ephZTCRj&nB~f)nuRGRsxT8TBaDmkyK?9= zBN)hW5LMmY{{umf7DS~&ZkOMzh@jn4 zF)J-G6N*D(%G>a$Tbo&(&+FF`?B8x*Af$N`9Epj}yQ!%zMq0KrG0}0IVnNq|^IRva zJVG5enCA(T3o8sf z9PtJEBV`p95pYTREr-cX2Ra`$)@Erh8C)UK9k zX(`U;!60REW5b&osn#}eyS3b~E8V9hp+1^}SqA+PxAOWt&bt_`%6&Ic3G)%??5Qd0i&1Rn(xpHNhChC7wqukwWa9u6!dp8cZ@}r{=-0Q_FFA zeLOTNxgJ+TrOQ{9=j&WcWM_VsH>~-He@ZChD~qNkauT89*HRsJ<84ito`fToGTGIgg@lE`ajZT<)xLon@2| zRKgc!?#`kC?zbea&peIF%_3QbiP0Sig^6L6FNF(<%|B!mKzt*7Jk|T7Dn`ul`08Zg zmw!I8qIh*(c{(_u91ngb?I(1%eX)AKp zr%@6S0y#9-xVfl6grr#)c&}o^)|fdif5hdhFdE6ijBw(vGy=Tr@6s{i?V$#(=JSNO zA{JB-b0EYkz8i46BS99rJrR|Qo4SLEKF{UzdZe5R<0>JM@tlEjDvqj42ppA!m}81( zom)vFJH}LCSjQSu=YAE%2P+J@^2kwfEMkC1i(;kvqsC=Et|S(oTf$7L?xS>tnuMt5 zkKPj&tg=|aUPtN>nq&eh66I{Rq2l-=-IU|9aoA`@S*WBWJqC}`W)&}_r1oQp9`O?z zvw?UT-Bc@wIdn1L9Zhn*EI~O#5#`RHjwsN@$@qbapehPfJdA>JgCrqP99kC`;vb0u z9wnt(Qy@yXAXiggyu{Xf-sW_s_#&BJW-4~?R9&`gg2hM^3!BmT2KS`aomSd@ldU+K zFuBPd79N#_+B`GjdLs%Bb`H^gBc$DLlki)o4_Bg?n5ZtYNl zLtmO2A53%Rdi73{wj7wz1*mX+ioY|$a-SLyAvbk1$KqNtQMJ{A)XiRM3d-%lKlx;thtCg~BlWMgK@r6%XoddD6ZQ?wq+$^=m!U|njJSWOj! z@#V~*xys_qa)nIQis{Wr%AneKEPl2onjVdqMB;f?ZAx4wn`dZVfpSL%++H=(V)Q@O zB6rseUxs2Qo71s~MfO8LabCD^w!-T%W4|cvX6iW6CKhDam2cxTsIX zGgaN8A+RXv%!)%~aAI9(Z-y*~b%D2Omd0)8dT~980@Qkgc_gi*kWna-t~v{mxdIt# zWy0(zggTNxi#j190XNZK25}1#L{wZ=4Zr44i!mAwB36-GiD?)sI;Ut#OKe{8`ZO#s z(KWQPQZly7x|%Y2EfffH*6c_*nG1@e#fl9#L=(*_Gpn_jH5&7|3b3SF zA+&8HZBQ&Za;nyEmvxIy%Arv#x6wfSKcWA`$5By>LveSGs+ z%e2I|(=7Z<+R?o{I&|{HDW5jgd3;~AIesXRZV4j>(a7pn)rfW5Q>nQ(&h}7Kp(vB9 zKrf@@az`^`AIA6+g{Yr@@?)O-dxkIWIWwvUw|vBEZ6BqRAZgqoZAX5AGhAV zA!k+Gx=D8T>x&Q3$zbWM#Cgq=#M>ywS|g~ThMXspzgvm^D2O+uk{oKQn18@L)mMtC zQc~`6+cwHq5xM%J;vsi6BDAqjg@nd|OhM_UF2cT4(jyp|{~CI0&SDULd1srqAjCy- zZHBiy9PF1HF0l4Yb3b>70CS1ktYgttba^=2N7C5x!j!RjpZLyHO)IVvv5s)(?} z;(0}!7NMk^4^_%fh^Poj9vvDgvgUqXz1FUqYeXzcJL%SEP^Q_T7E8_JE9})Gr=mcMHb0)oaP(BV@NkSVkCJl*TLDK&rREjAs0!k+ zL~^t^A!r%wtAqGaF`;ucJ^CDdw21obceHp``Q~VG;}Oa+#Xbr~%``{u-DxiQ9MahogfXRyQwYs^s6srOeVls z>S6+Sn3iTO0<7JXxhH03a&`(Rjfx=wxMKE-oL*C?qFFQO&D5|B3zosT+63+N0^K|U zi*?OYAGvcYL);fCn42yOXG-A-=vjui;=#;-xxONiQhb!A-tL{PejtSs38ZUgF}%BE z+00P!1Z(sa$N;phQSCm8zbG%&hZe(|7HXj_AlA$)q$i_aUZEzZI9kLk!yI=dr%}Da z_z=OyahF<(`5a1WS@Xy3+Sp+RiL%_e@t{DM4N`U-x1p*=&iQpnMI^LL%Ba5%RPi(Kj}R0jsXP-{i} zey*CSphnZ{|N4@Z^rQ;L7*y`xkYA4HA9|Mb$$MQ{I{wW3oppWQY-PNhDczhzvrfWq zC^qEn0rWYY{HYh|&0!;HWi7*c+wQs8S}-gk%Tvy8sDob%6Yo;BpwE0}68bFBKnltV zU`wK+j&xw*r+%HaYS&eQL|5ie387jv3|OyHK<&WrQ?V5L$EV-?6b5$}lxoV>&}H8) zr>uNAj+PpcJ2R)2yl&y2csp$r9H6ZEM=dz$i}hOSS8?rh)w^oW4%2Lq$v73$Gu{-@ zg1j@#c4fSWL0lk9F=1lt&IYO=UV3Q-Dl0vGN9=Ub#HbUEv}QfxzsRk zt}?pxJCakF>slAQ+9!hByD4mf8f`XEl zyx}CHUgfM#LWTvfTEFF~(*?YY^;;IPv4RG(TiyEjXhWfc+J$nZb4@s1W`vfFB$Z(+ zFC5?6ka{HFRS=4?I*j;Pyit@vIUPgEno?u30;g%R69^C0S9^y30+}5cD^e4lIdt1K zTHAVfiUCieYAdANK+*$KQGptXUbn`GWxZ&+GQdFRkQZg_6>e;-c*IvHf!gdt(=FAH zr*i0kld;QTU0T;AsVdPGa(lfA%0x(C1{hKGjo124-Ufw)Y7OG~p>8OlK`75(PrlVY zt)2mE`O4)gN?#h+Ea|0Dw>%sPgkhqbWW=&8V-#0OHaBUY*3xy-Hd!h82wOSH7LB%} zmDoX<{7)IfQc%#v#!05XWw~#9>e5kbP0Lk7OsN=nTqtv3Vp1eKhM}W#IomgH(yVQB zsLHt7tkSTnF^Gq>)(ZH~sjmzmpE9G6U1S=I+-vngsv(;7S^KS~x1iG>!Ja?m0QJ7A zkvl@f(MBmg+PJW!Hk4;=T$C*gBJkZNKuZIBDweLk+S{V*$034n`pgtL0a^fgiO;di zkK|$AZPs^u+voyf8)=RknqIXCpfZ`q+*=k;e2Q6?{sF@SB^3EwY_zV# zSk)aWg!!--2T=habrN$adA9no%8=~lW+-3}$aE(A1#mal4k<^wNLWFvq}4_sn*s3o zA&WQllGU54;HNbbz9=uNEs&$FZghG?qcOzt6vPMEWUawxS(>qTa1jD zM`+6B&9!A{%n()w*OK?LT}BBuWgvT~9>B@PpdPKexl`!4J0Qp3=tCC<3$(Cun&#Tl zSdt1!HU|&0M^G4u3D&uq`AG-~Lq}u!v7MRCr57)%BmPvv6|ZmkEGI(cV43dJ725iD z$oNp}7h-q9&+caPsxX_Sh#8;mVeG9aAB-zKcfXZ1VH_qQ7GnSsG`xN^&AO@Lnp`rKz{oDGkv;^K0a+*#G_1(fvc`?g zK6PwB4QUcWC>gh0ht{@PN8{ZQo%^UAab01Dld$S&n&p&CX3*%azej;JX*GyFKD^gMAX}#vPZ8Eph zx9#~Op9N!cMP+E9+p&GFBZbY`_&ha@Lblh^t#^#FtlBPcH6`Vd^vI+}i!3F)y8}Mf zvx)&&iq6pV529?g$V-XK+YDbA_4vI0?0A00G|ihMFr}2CZD-MXQX;*89M)u;?G*ln zmO4cvdeSY}9F|Ss6zhohGpkFnOh%S(j0uzPrjXc0w3S02YLIHOsRscu#?xT;G5(PI zlT-3;WPvt0x8qG_o2)Tonu{PW*3zbRoYR}37F{076V~5y{M}}J=cLY3JCy=L&f0as zj1%O1ZCyXjDP6;XuIx>o>BLP~kHhl5q19FFIR$&pDPmHoAZx6R`6wmmRcD#Su*qRF zaI!i=unCq8A3cN*IKW;&EYxMynWP^)uxj-cv1r)7bxU-mbFs{pdd4;`%?f@c7;vTK zI9{&CoQGRYl82YiOuE$JLS;toqgg(n7EMg~u~~9!1I(8-eP1VJ@u5{^CVDX#P?i8z z`!36O$mXzP2LbweF2#P##qLC#ytIZZ&_gOjsvg1G65HAL6pPKD%@P0bP)e)`ZmfrX zWIJ6c>~Y+@qBwCv^>gB4ux|^K4I38P)jbPxwvErv-JtXV<>KqtBG|meQr_+Ixg$Q8 zp>4fiiR)|+{jLXn**nP1gOHrFU6?Flv!g%y^pE^Xn zm+Nw8E1P3+>nrEC&H$|u1Gw5DHos}FW$+KK?Jzeq4IjTQAgd0rAEZhn~@PNL>72o@yWP2=eIAqP>A> zo$hZgLCipldPt8JZ=>F}cC$KQG$rz)oN0>_?hhOxP@SKuI2giAyzrPA*%oH#32nZ{ zxUl)g9--qsYG(D!@RjZNt)lvcdATjEx{D@g9({@*nlEyT8CqcZ~-Qo-fzI+(E-;J2NTXV}?CC<|e1Ip(lK1kx*-7YAvjG1)GYo zHgu-tjb%tw6h-q_5F^fBX1PfA{t!=_PpY?vtqt)hwZJrg;+2X_(X4nY7sX0E1xIda zxj^s~5VU2f$&9JIiEO-#;vg$F>^GO8(q|rF=o#mD<9NlzgB}*A_T{RPc?5o1s5vmB}E_K6j6r2=&Zkw&LKhG^wPoex@AO8|Tz9a;TV z6Z977W+AfY78A{5#;drYaq)SS;a35oVM$_-YD4=GH&?BR>}a>&1e52soYyvjLw562 zpO@BqI7J3)Bi{R2+kl)~D2>FxEK~%fwL$@1Kf|-uT-@!KG*BVCrhN4y1&__nZx?KsL^c%DFdU`vPo7qiD z>&F^Iu(p}$2(-oa;9jC<*n9!t0y*B9(>=U?^Q-(es~Hr}n-&r|#y8>9t@vdsRD0(6 zRPl&0Jy5*cwt1`1#m2Ul66B9DwLaY*dt%GR^HGZClY`ieFL&szcF2C`h>Y|4ijnGf z<(L;InJbSZ$sJ7FpG{7`NB!6jx+xzlZo;lmwsB2{^3Szv4^=dTs4ZDZ79cN0`f57x zyEP?1rmCJ{J(=9>1C4=xRf1()r0Ql099^kUV((Xw6ANzru)4B|a>?n#`c$sl7g0OC zY=@8=R~tojwjFrzW|${n9L9wk`bVt1k;50kn$Mbn|!CZHlM4O~VF>xJN?SGOO_N`#{dF zT~jLx3vr+`@pb~u5yxt_#vXDXfShtE=Myr#T+XaWrhcb~H!~}YDZVK;+sJkuLm6*?@ zW*X6`rL#U}W4G5+d2853ELNG(XBY;&u?GTE#RA%lk;r~w&0)Fp)cid92}6z>a%Q@i zL$X3fc|`O}L%F+ZhhqF}S45;L%RsptN7uxXZy@)Gttjw$GYZspZzeHY&0}t#HFBgz z(%D2vOm)b`95-D9qKP}Og(9m;V?%UD3EPFsD}( zBCB#+cm-E0+au}PA)JYl4gZQ`sKc;vgUuyKMD4zc8rTz%Bb92s7@s`k^4wHh%Hc@O zcTr1d2}=2-5if?7XtF;e;7D_2@*ks7-Lsp<#~1Z`0?czN`i_?)jXv5mYmx%1F}`t$ z`Z5wW?4Fz6Z5U-4h7-<2xe-DwA+ZXU=w^DuRGOBtc`hIGHR}3W`U;?yDmnHFCTuv! z4hRW0Y3jl$-Z~b2g4$bD-n#s+cw*gjVoV7}O?h!Hd?Sd#lHqKac*FHz1NKQ8Y??7|urJRq?z=raynca+L{NN!WvAx43+W zzUfs_fNu3-3p38rmJfnq3wb9gTC@cP;?_+~%;mk+ZocWO2tjTdP#5gV3MR>!V%|h7 z7YL|W#1zzNTrJVM-;5i3pid0Egy?9VIHP zW)!d5%5eEjo6cB?LfzYUD?}oXx&a|%p#;j(#f*;WI?2oz{4^MAIUU0Sy}9&9D>_FS zE!O;eJ2dP=(rC_)V_lR+i=bGqpq$QyNm&{jS@KWJ!B$p0s6}a#qeJ^P{Kx%ARpg%qF2aMrR0)iU&$=DpUOom!fy3s=pnV|AuV;oRv^8j=HY4Si($i3u5Z zvnf+i-P5wwN`6dy0<4p32VJ|Xf7k+HD5~rjI%qF-2F+?7 zWh+m<>Xe_l5s1y^?=Wau4#(oI3t2xYBPbgK)bHUo2eK0EI4k`qU&!{jg$lAXRI?r# zHt#5pv#k{`P~Xq7gvHx6FoTu0#dONIZ4>?Imlao#rs8XhO$%$wC+|ftvh+>W*sTal zOxtEuhw`d2tDm`*V)3-@l~}xOTO3w1aLaeBc1H!p-GuF+-}2Q#SHSBZdQ&Udbg3ws zH)Od1(1>J>V`sBQlpLCQ^n)DA=-TDWCBZ0?qXnr)EoX7eLmi>|OgY|wN3D9o>Qlrcm{DuC8|Uduu|WF9P1 z@|Llqq~_9?o6eJ*`t4Lmpik9$*YVwIHkFa1BX97S$~m6s$d8$cqhkPfE!j76Wb;M^ z#=GyZld_BUI67%cS>k2e4wn(bn5tr}0}ZXGjHD#WpiYo=6+u2!PU{QHZO2*#cPJYY zCXU+0Xi-JD_XRR>dQ8y?o4{I+BXPOuj!uwHbxBR>eR-G06Jf^FiANBAS@Ox!FYGif zO3^JGtSi<|akj=|=Y^1d`nmkADCUhb7R9cEuL9*Q2)V^e2}v~dtApLp#p|jC77X;* zIE`T5t0lJ#8gp^F2IUb%S-B6$o?6qdD>|;Ub;9Z$9SgnT%(^#Rhua)c5~Lz)f0#F3 zEz_7&l}aAz;|LR@bm1I;PY%BW}yB zk}5S;25N!{LN6GwM5(W@hk#LU*h~{+vt)V7%KC#ej`CrJ7Dsk>Z#kK@;XxH#+NYP~B&}CE9Z9g*`w`4f!sw zT-9fu97`{-a}s+p^PYy73Dh3Tc%uX2x<|SPGONv`SfyhYYBD&TnX=KM5p3wR?z7#V zVYPO5;i0j(F;t*Y-}-i@ZLAtYqC8R@7n@-B87H@nz6d*}^_Qb_TRg?q#nBo2C|$}O zxu6jJp{XwAW~Vse2HUcqYUpe#Lv5F>bpf5*Vq!P2%h5dbgLsxe#l7rK8KRxRob8#4 zRwBkz)I032FR)_HRX951UQm0&+;Y~taTcIAjN!ppXBwOspqWGti?BgU^Wm ziv(gdgjgE3tDch_%#a=W0;q!bAB-EPT-J9O9Gbe&$s;i2z#gJ{4$1bYnsSKYsRN1! zIRa=h#7UV;Fz#^gkEo}Z+CoVVZ~40#6raYgJjF&1 zMz(%oy;AyPxmvp}$?3F6;2lbi7IVJd@GE!BKu`;_DO6>g0C;MH9_yeM$^12IBF+?hNWfYBaE-ybk| zScn{c&7of^PBK)!@wq-eb6m~@puiEMZ+KW)<(o}chl|nC4ru-yHeFRY zS=ND9L5xQrjl(%+g)yKUeEd%RsBKJ-GoYRk;4dT15ko@`YHx^~W?9&ZbX5Ts7jM*PO%dqpk$cA?z)L5Q|1qrK&{(K1SsoU$*Z`X*#~S}n{^ z3)pf{n)z5Q8V^LFpa%_z|B@NKE!5cEl32 zk<*-DtFlF7Fr3&nlb-O{MxKNB0?*svi*Ow=tnZ1Jv7yzU0)bvHJ;;l_Fm z>0ed8Ss^h^3JnAs5z2#Z5|tu7h;4_mz0QBZ)}50!$OU3T4RRY8=xE@R>>BjQ z>YCQ6K|<9OUnJ=ACAJ{JIn>DM&sEOQZP(rE#OG}dtF}#U+uX$Mbx94YHpP}`BCC!Y zDZO3;#RYD~i6kw2TO^#3_)jw)S1dydCN}rG1I*hRIscjN4OhKOR+-c@1&y3{@{x0A z!=zi1ZmL@OEbkxmEU!Gpt3SbOd3jfVZrA$AuKBJm9@DLSL-#NLhVCExaBjTUax34t z{WIRV{qx_pjSd@Ev|-9$?rq!XxM?M0=l-#8+ZK;s5}i4HOi9 zkK9&1a$EVxZRI1km5PYnZ-{JEt@pD@`2kp58Of$D|viCap7p1 zw2%J0ZPD7{Wqpi`LEpzp8xM_V4(z?O*hb+LD=TOXrV>uA5oB zaHcT}MmH^pjvD{FJWPxHOXjRAn>4Fr@}lUF5i~8AtXx_;x3Ka(+CTg~+UUBqB@2d` zy14({w`fZT&o7>+4#qf>7z^ME|m4v|CdK- zF=8tpp^f_}Xz{2~rJI)g$?wlb`%dBggyLoYW@Z1H<)xFRHFgxO8CJS}hyc#Aq~BWA zwBvekwye*jXdjbJ5Qj#F(bdbO)XH~e|KN9K%O^-5#p5O% z{dw8q@q=lmi4L3-UG$8jc>dVp8HLf+i%P~Vag@ziTr!Ji7xA4nKRRoU9%b~1lDSKd z@pV}w`HMd&EA!bZkkv+cVcw$ppu#E8;cA2al;Qg703Fd zETZeg@Ta{hTeNXd@!HY=N!0|sTi*&-w zN(xt5^Z7kql`VT}eA)EAI;eb9R=3)!d{nmbQQ5!6qp~FfW)zPrWPy0v?9zENzv$Di zbipvOKwZ7Obijh>!U@rV{r{|IWyR*S@>SWGS7oDf9*cQTws=aP=*Hn}2BLOPS#r0$ zDT`3qQvDsClx2PCz}d1+Dx6R{V{XiwvPBz4lx$e^-+xiIWYW6m;I$6ez!;X)#X}#9 zjv5~wv!Q6+ta4!^=a%*9D`AyS%O1l$T}A6~KT0VcFusF}xyF8wE&@ zaVp=LwY)P+vO?uEvz5=x9_KT&WqsF_O&|DcUzsg_tS^mAmTvx#mu7{z{pxpSk-lv3 zh|;+WVTTx9y{xSN%IM+&rGuA44_UNnM#-Y3618Z}h?2=`N}hh|m>!gcT?VBoUA0^s z0*q5y=G(C(xU=*#a5jIHu3tl6dh`CDJ``Irhl%HZ@ts(-%(hGZ2fq_rHhx&~*p0G2 ziw=C6-EjPdH)4^Gy&08{#8y5Mdu)%yig_n^+;O}QTe_%^<8SdiZ0X!}(LqBU@gIhz zNr$BKk`*(f>&H2c?RD6)zSBzMyRaq?ur9&= z>_=fuLos89wIwmsdq%|4)r+GW$Jk^2iLb!MLEB&Z5m@VaBquGjc#XMecyZxqYc>Ao z-hMUh&z0G7`6Lyzvhv+mdzfB(bDUyJtK7{lmCwEgDxZD*-+1;F>r2P)`tEDdrbVT5 z`#Jv7uf9eHEQ>CjXn*$=euR$bqQ@(reKm?z?Q&K=`+98I{`zNMi$_n1E*Vz-*;n|N zEFKV@GU8Xf{EFmd6Q-1nSQ%Y7q4M?D%GY22@Yi33hXRPndxFPvFX)sOu}R}#9*#xGTt7BoLtoWT$b zD~3)Ji=M&DRYfabY(0(_TZ^CSSG>IMaX#2uJaST?yDM0N!yNw`jwN=o5X2d6ukt3?^|!YX|*R-()4S zDW15vXiXogK3fkd!&OngS3b*H`7G=2`7CSMjH%J7!~T8`vl3q^nKqk^78gz|o;LK#tfm#Z zbsw~Yeu0%39{<06eAT=P-S{#URU)peSy=f5>)-7OR;%qwboK0_4O5Co{<~!EFh_Lp zg32dYk0UKxm=2gxynI~A>ba%s7elf)#>$@c!=sa@m-Jg(v~D~J&Lzv&m8@JUJf(a} zS_+us?RR*8)ht1o5FKCLCyI&*=3p_e59?VxH!mkcgh zI3&8!Ts;^I~noON^@xw=oOJkw!TJQ2tHT zl2IF@Q|4CmqN*GqjgBrX+OYCZe^Hgsu^roks&dT2*yxE-9Yi-RDC;w=tnbL;O&f86 ud>@DXF;&|(Q8}s9QPE?nVw`mxFR32iQ>m4&p&s9BsHR+e^cPWi3G;tUB5Do* diff --git a/rhodecode/i18n/zh_TW/LC_MESSAGES/rhodecode.po b/kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po rename from rhodecode/i18n/zh_TW/LC_MESSAGES/rhodecode.po rename to kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po --- a/rhodecode/i18n/zh_TW/LC_MESSAGES/rhodecode.po +++ b/kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po @@ -1,4640 +1,5617 @@ -# Translations template for RhodeCode. -# Copyright (C) 2013 Marcin Kuzminski RhodeCode -# This file is distributed under the same license as the RhodeCode project. +# Chinese (Taiwan) translations for Kallithea. +# Copyright (C) 2014 RhodeCode GmbH, and others. +# This file is distributed under the same license as the Kallithea project. # Translators: # FIRST AUTHOR , 2011 msgid "" msgstr "" -"Project-Id-Version: RhodeCode\n" -"Report-Msgid-Bugs-To: marcin@maq.io\n" -"POT-Creation-Date: 2013-06-05 19:55+0200\n" -"PO-Revision-Date: 2013-06-02 13:23+0000\n" +"Project-Id-Version: Kallithea\n" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2014-07-02 19:08-0400\n" +"PO-Revision-Date: 2014-02-13 14:34+0000\n" "Last-Translator: marcinkuzminski \n" -"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/RhodeCode/language/zh_TW/)\n" +"Language-Team: Chinese (Taiwan) " +"(http://www.transifex.com/projects/p/Kallithea/language/zh_TW/)\n" +"Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -"Language: zh_TW\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: rhodecode/controllers/changelog.py:149 + +#: kallithea/controllers/changelog.py:90 kallithea/controllers/compare.py:90 +#: kallithea/controllers/pullrequests.py:265 +msgid "There are no changesets yet" +msgstr "" + +#: kallithea/controllers/changelog.py:186 msgid "All Branches" msgstr "" -#: rhodecode/controllers/changeset.py:84 +#: kallithea/controllers/changelog.py:189 +msgid "(closed)" +msgstr "" + +#: kallithea/controllers/changeset.py:87 msgid "Show white space" msgstr "" -#: rhodecode/controllers/changeset.py:91 rhodecode/controllers/changeset.py:98 +#: kallithea/controllers/changeset.py:94 kallithea/controllers/changeset.py:101 msgid "Ignore white space" msgstr "" -#: rhodecode/controllers/changeset.py:164 -#, python-format -msgid "%s line context" -msgstr "" - -#: rhodecode/controllers/changeset.py:345 -#: rhodecode/controllers/pullrequests.py:478 +#: kallithea/controllers/changeset.py:167 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:209 kallithea/controllers/files.py:98 +#: kallithea/controllers/files.py:121 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/changeset.py:355 +#: kallithea/controllers/pullrequests.py:482 #, python-format msgid "Status change -> %s" msgstr "" -#: rhodecode/controllers/changeset.py:376 +#: kallithea/controllers/changeset.py:386 msgid "" -"Changing status on a changeset associated with a closed pull request is not " -"allowed" -msgstr "" - -#: rhodecode/controllers/compare.py:74 -#: rhodecode/controllers/pullrequests.py:256 -msgid "There are no changesets yet" -msgstr "" - -#: rhodecode/controllers/error.py:69 +"Changing status on a changeset associated with a closed pull request is " +"not allowed" +msgstr "" + +#: kallithea/controllers/compare.py:194 kallithea/templates/base/root.html:65 +msgid "Select changeset" +msgstr "" + +#: kallithea/controllers/error.py:72 msgid "Home page" msgstr "首頁" -#: rhodecode/controllers/error.py:98 -msgid "" -"The request could not be understood by the server due to malformed syntax." -msgstr "" - -#: rhodecode/controllers/error.py:101 +#: kallithea/controllers/error.py:101 +msgid "The request could not be understood by the server due to malformed syntax." +msgstr "" + +#: kallithea/controllers/error.py:104 msgid "Unauthorized access to resource" msgstr "" -#: rhodecode/controllers/error.py:103 +#: kallithea/controllers/error.py:106 msgid "You don't have permission to view this page" msgstr "您沒有權限瀏覽這個頁面" -#: rhodecode/controllers/error.py:105 +#: kallithea/controllers/error.py:108 msgid "The resource could not be found" msgstr "找不到這個資源" -#: rhodecode/controllers/error.py:107 +#: kallithea/controllers/error.py:110 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." msgstr "" -#: rhodecode/controllers/feed.py:52 +#: kallithea/controllers/feed.py:55 #, python-format msgid "Changes on %s repository" msgstr "修改於版本庫 %s" -#: rhodecode/controllers/feed.py:53 +#: kallithea/controllers/feed.py:56 #, python-format msgid "%s %s feed" msgstr "" -#: rhodecode/controllers/feed.py:86 -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Changeset was too big and was cut off..." msgstr "" -#: rhodecode/controllers/feed.py:90 +#: kallithea/controllers/feed.py:93 #, python-format msgid "%s committed on %s" msgstr "" -#: rhodecode/controllers/files.py:89 +#: kallithea/controllers/files.py:92 msgid "Click here to add new file" msgstr "" -#: rhodecode/controllers/files.py:90 -#, python-format -msgid "There are no files yet %s" -msgstr "" - -#: rhodecode/controllers/files.py:271 rhodecode/controllers/files.py:339 +#: kallithea/controllers/files.py:93 +#, python-format +msgid "There are no files yet. %s" +msgstr "" + +#: kallithea/controllers/files.py:301 kallithea/controllers/files.py:361 +#: kallithea/controllers/files.py:428 #, python-format msgid "This repository is has been locked by %s on %s" msgstr "" -#: rhodecode/controllers/files.py:283 +#: kallithea/controllers/files.py:313 +msgid "You can only delete files with revision being a valid branch " +msgstr "" + +#: kallithea/controllers/files.py:324 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:346 +#, python-format +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:350 kallithea/controllers/files.py:416 +#: kallithea/controllers/files.py:498 +msgid "Error occurred during commit" +msgstr "" + +#: kallithea/controllers/files.py:373 msgid "You can only edit files with revision being a valid branch " msgstr "" -#: rhodecode/controllers/files.py:297 -#, python-format -msgid "Edited file %s via RhodeCode" -msgstr "" - -#: rhodecode/controllers/files.py:313 +#: kallithea/controllers/files.py:387 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:403 msgid "No changes" msgstr "沒有修改" -#: rhodecode/controllers/files.py:322 rhodecode/controllers/files.py:394 +#: kallithea/controllers/files.py:412 kallithea/controllers/files.py:487 #, python-format msgid "Successfully committed to %s" msgstr "成功遞交至 %s" -#: rhodecode/controllers/files.py:327 rhodecode/controllers/files.py:405 -msgid "Error occurred during commit" -msgstr "" - -#: rhodecode/controllers/files.py:351 -msgid "Added file via RhodeCode" -msgstr "" - -#: rhodecode/controllers/files.py:368 +#: kallithea/controllers/files.py:440 +msgid "Added file via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:461 msgid "No content" msgstr "" -#: rhodecode/controllers/files.py:372 +#: kallithea/controllers/files.py:465 msgid "No filename" msgstr "" -#: rhodecode/controllers/files.py:397 +#: kallithea/controllers/files.py:490 msgid "Location must be relative path and must not contain .. in path" msgstr "" -#: rhodecode/controllers/files.py:431 +#: kallithea/controllers/files.py:524 msgid "Downloads disabled" msgstr "" -#: rhodecode/controllers/files.py:442 +#: kallithea/controllers/files.py:535 #, python-format msgid "Unknown revision %s" msgstr "未知修訂 %s" -#: rhodecode/controllers/files.py:444 +#: kallithea/controllers/files.py:537 msgid "Empty repository" msgstr "空的版本庫" -#: rhodecode/controllers/files.py:446 +#: kallithea/controllers/files.py:539 msgid "Unknown archive type" msgstr "未知的存檔類型" -#: rhodecode/controllers/files.py:631 -#: rhodecode/templates/changeset/changeset_range.html:9 -#: rhodecode/templates/email_templates/pull_request.html:12 -#: rhodecode/templates/pullrequests/pullrequest.html:124 +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:12 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/pullrequests/pullrequest.html:123 msgid "Changesets" msgstr "變更" -#: rhodecode/controllers/files.py:632 -#: rhodecode/controllers/pullrequests.py:149 -#: rhodecode/controllers/summary.py:76 rhodecode/model/scm.py:682 -#: rhodecode/templates/switch_to_list.html:3 -#: rhodecode/templates/branches/branches.html:10 +#: kallithea/controllers/files.py:776 kallithea/controllers/pullrequests.py:160 +#: kallithea/controllers/summary.py:76 kallithea/model/scm.py:818 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:13 msgid "Branches" msgstr "分支" -#: rhodecode/controllers/files.py:633 -#: rhodecode/controllers/pullrequests.py:150 -#: rhodecode/controllers/summary.py:77 rhodecode/model/scm.py:693 -#: rhodecode/templates/switch_to_list.html:15 -#: rhodecode/templates/tags/tags.html:10 +#: kallithea/controllers/files.py:777 kallithea/controllers/pullrequests.py:161 +#: kallithea/controllers/summary.py:77 kallithea/model/scm.py:829 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:13 msgid "Tags" msgstr "標籤" -#: rhodecode/controllers/forks.py:176 -#, python-format -msgid "Forked repository %s as %s" -msgstr "" - -#: rhodecode/controllers/forks.py:190 +#: kallithea/controllers/forks.py:191 #, python-format msgid "An error occurred during repository forking %s" msgstr "" -#: rhodecode/controllers/journal.py:110 rhodecode/controllers/journal.py:153 +#: kallithea/controllers/home.py:86 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:91 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:15 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:73 kallithea/templates/base/base.html:90 +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/base/base.html:394 +#: kallithea/templates/base/base.html:565 +msgid "Repositories" +msgstr "版本庫" + +#: kallithea/controllers/home.py:132 kallithea/templates/files/files.html:33 +#: kallithea/templates/files/files_add.html:37 +#: kallithea/templates/files/files_delete.html:37 +#: kallithea/templates/files/files_edit.html:37 +msgid "Branch" +msgstr "" + +#: kallithea/controllers/home.py:138 +msgid "Tag" +msgstr "" + +#: kallithea/controllers/home.py:144 +msgid "Bookmark" +msgstr "" + +#: kallithea/controllers/journal.py:114 kallithea/controllers/journal.py:157 msgid "public journal" msgstr "" -#: rhodecode/controllers/journal.py:114 rhodecode/controllers/journal.py:157 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/controllers/journal.py:118 kallithea/controllers/journal.py:161 +#: kallithea/templates/journal/journal.html:15 msgid "journal" msgstr "日誌" -#: rhodecode/controllers/login.py:138 -msgid "You have successfully registered into RhodeCode" -msgstr "" - -#: rhodecode/controllers/login.py:159 +#: kallithea/controllers/login.py:187 kallithea/controllers/login.py:232 +msgid "bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:193 +msgid "You have successfully registered into Kallithea" +msgstr "" + +#: kallithea/controllers/login.py:237 msgid "Your password reset link was sent" msgstr "您的密碼重設連結已寄出" -#: rhodecode/controllers/login.py:179 +#: kallithea/controllers/login.py:257 msgid "" -"Your password reset was successful, new password has been sent to your email" +"Your password reset was successful, new password has been sent to your " +"email" msgstr "您的密碼重設動作已完成,新的密碼已寄至您的信箱" -#: rhodecode/controllers/pullrequests.py:136 -#: rhodecode/templates/changeset/changeset.html:10 -#: rhodecode/templates/email_templates/changeset_comment.html:8 +#: kallithea/controllers/pullrequests.py:140 +#: kallithea/templates/changeset/changeset.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:15 msgid "Changeset" msgstr "" -#: rhodecode/controllers/pullrequests.py:146 +#: kallithea/controllers/pullrequests.py:157 msgid "Special" msgstr "" -#: rhodecode/controllers/pullrequests.py:147 +#: kallithea/controllers/pullrequests.py:158 msgid "Peer branches" msgstr "" -#: rhodecode/controllers/pullrequests.py:148 rhodecode/model/scm.py:688 -#: rhodecode/templates/switch_to_list.html:28 -#: rhodecode/templates/bookmarks/bookmarks.html:10 +#: kallithea/controllers/pullrequests.py:159 kallithea/model/scm.py:824 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:13 msgid "Bookmarks" msgstr "" -#: rhodecode/controllers/pullrequests.py:321 +#: kallithea/controllers/pullrequests.py:330 msgid "Pull request requires a title with min. 3 chars" msgstr "" -#: rhodecode/controllers/pullrequests.py:323 -msgid "Error creating pull request" -msgstr "" - -#: rhodecode/controllers/pullrequests.py:343 +#: kallithea/controllers/pullrequests.py:332 +#, python-format +msgid "Error creating pull request: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:354 msgid "Successfully opened new pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:346 +#: kallithea/controllers/pullrequests.py:357 msgid "Error occurred during sending pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:385 +#: kallithea/controllers/pullrequests.py:397 msgid "Successfully deleted pull request" msgstr "" -#: rhodecode/controllers/pullrequests.py:481 +#: kallithea/controllers/pullrequests.py:485 msgid "Closing with" msgstr "" -#: rhodecode/controllers/pullrequests.py:518 -msgid "" -"Closing pull request on other statuses than rejected or approved forbidden" -msgstr "" - -#: rhodecode/controllers/search.py:132 +#: kallithea/controllers/pullrequests.py:522 +msgid "Closing pull request on other statuses than rejected or approved forbidden" +msgstr "" + +#: kallithea/controllers/search.py:135 msgid "Invalid search query. Try quoting it." msgstr "無效的查詢。請使用跳脫字元" -#: rhodecode/controllers/search.py:137 +#: kallithea/controllers/search.py:140 msgid "There is no index to search in. Please run whoosh indexer" msgstr "沒有任何索引可以搜尋。請執行 whoosh 建立索引" -#: rhodecode/controllers/search.py:141 +#: kallithea/controllers/search.py:144 msgid "An error occurred during this search operation" msgstr "" -#: rhodecode/controllers/summary.py:182 +#: kallithea/controllers/summary.py:203 msgid "No data loaded yet" msgstr "" -#: rhodecode/controllers/summary.py:188 -#: rhodecode/templates/summary/summary.html:149 +#: kallithea/controllers/summary.py:206 +#: kallithea/templates/summary/summary.html:105 msgid "Statistics are disabled for this repository" msgstr "這個版本庫的統計功能已停用" -#: rhodecode/controllers/admin/defaults.py:96 +#: kallithea/controllers/admin/auth_settings.py:127 +msgid "Auth settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/auth_settings.py:138 +msgid "error occurred during update of auth settings" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:97 msgid "Default settings updated successfully" msgstr "" -#: rhodecode/controllers/admin/defaults.py:110 +#: kallithea/controllers/admin/defaults.py:111 msgid "Error occurred during update of defaults" msgstr "" -#: rhodecode/controllers/admin/gists.py:56 +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:289 msgid "forever" msgstr "" -#: rhodecode/controllers/admin/gists.py:57 +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:258 +#: kallithea/controllers/admin/users.py:290 msgid "5 minutes" msgstr "" -#: rhodecode/controllers/admin/gists.py:58 +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:259 +#: kallithea/controllers/admin/users.py:291 msgid "1 hour" msgstr "" -#: rhodecode/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:260 +#: kallithea/controllers/admin/users.py:292 msgid "1 day" msgstr "" -#: rhodecode/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/gists.py:64 +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:293 msgid "1 month" msgstr "" -#: rhodecode/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/gists.py:68 +#: kallithea/controllers/admin/my_account.py:263 +#: kallithea/controllers/admin/users.py:295 msgid "Lifetime" msgstr "" -#: rhodecode/controllers/admin/gists.py:127 +#: kallithea/controllers/admin/gists.py:147 msgid "Error occurred during gist creation" msgstr "" -#: rhodecode/controllers/admin/gists.py:165 +#: kallithea/controllers/admin/gists.py:185 #, python-format msgid "Deleted gist %s" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:50 -msgid "BASE" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:51 -msgid "ONELEVEL" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:52 -msgid "SUBTREE" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:56 -msgid "NEVER" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:57 -msgid "ALLOW" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:58 -msgid "TRY" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:59 -msgid "DEMAND" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:60 -msgid "HARD" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:64 -msgid "No encryption" -msgstr "無加密" - -#: rhodecode/controllers/admin/ldap_settings.py:65 -msgid "LDAPS connection" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:66 -msgid "START_TLS on LDAP connection" -msgstr "" - -#: rhodecode/controllers/admin/ldap_settings.py:124 -msgid "LDAP settings updated successfully" -msgstr "LDAP設定更新完成" - -#: rhodecode/controllers/admin/ldap_settings.py:128 -msgid "Unable to activate ldap. The \"python-ldap\" library is missing." -msgstr "無法啟用LDAP。找不到python-ldap函式庫" - -#: rhodecode/controllers/admin/ldap_settings.py:145 -msgid "Error occurred during update of ldap settings" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:58 -#: rhodecode/controllers/admin/permissions.py:62 -#: rhodecode/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/gists.py:234 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:263 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:268 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:271 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:127 +msgid "Your account was updated successfully" +msgstr "您的帳號已更新完成" + +#: kallithea/controllers/admin/my_account.py:141 +#: kallithea/controllers/admin/users.py:207 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:161 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:171 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:213 +#: kallithea/controllers/admin/users.py:432 +#, python-format +msgid "Added email %s to user" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:219 +#: kallithea/controllers/admin/users.py:438 +msgid "An error occurred during email saving" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:228 +#: kallithea/controllers/admin/users.py:449 +msgid "Removed email from user" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:274 +#: kallithea/controllers/admin/users.py:315 +msgid "Api key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:286 +#: kallithea/controllers/admin/users.py:331 +msgid "Api key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:290 +#: kallithea/controllers/admin/users.py:335 +msgid "Api key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:62 +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:104 msgid "None" msgstr "無" -#: rhodecode/controllers/admin/permissions.py:59 -#: rhodecode/controllers/admin/permissions.py:63 -#: rhodecode/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 msgid "Read" msgstr "讀" -#: rhodecode/controllers/admin/permissions.py:60 -#: rhodecode/controllers/admin/permissions.py:64 -#: rhodecode/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 msgid "Write" msgstr "寫" -#: rhodecode/controllers/admin/permissions.py:61 -#: rhodecode/controllers/admin/permissions.py:65 -#: rhodecode/controllers/admin/permissions.py:69 -#: rhodecode/templates/admin/defaults/defaults.html:9 -#: rhodecode/templates/admin/ldap/ldap.html:9 -#: rhodecode/templates/admin/permissions/permissions.html:9 -#: rhodecode/templates/admin/repos/repo_add.html:10 -#: rhodecode/templates/admin/repos/repo_add.html:14 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:9 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:13 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:9 -#: rhodecode/templates/admin/users/user_add.html:8 -#: rhodecode/templates/admin/users/user_edit.html:9 -#: rhodecode/templates/admin/users/user_edit.html:133 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/admin/users/users.html:85 -#: rhodecode/templates/admin/users_groups/users_group_add.html:8 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 -#: rhodecode/templates/admin/users_groups/users_groups.html:9 -#: rhodecode/templates/base/base.html:317 -#: rhodecode/templates/base/base.html:318 -#: rhodecode/templates/base/base.html:324 -#: rhodecode/templates/base/base.html:325 +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/auth/auth_settings.html:12 +#: kallithea/templates/admin/defaults/defaults.html:12 +#: kallithea/templates/admin/permissions/permissions.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:12 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +#: kallithea/templates/admin/repos/repo_add.html:13 +#: kallithea/templates/admin/repos/repo_add.html:17 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/settings/settings.html:12 +#: kallithea/templates/admin/user_groups/user_group_add.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:13 +#: kallithea/templates/admin/users/user_add.html:11 +#: kallithea/templates/admin/users/user_edit.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:13 +#: kallithea/templates/admin/users/users.html:58 +#: kallithea/templates/base/base.html:342 +#: kallithea/templates/base/base.html:343 +#: kallithea/templates/base/base.html:349 +#: kallithea/templates/base/base.html:350 msgid "Admin" msgstr "管理" -#: rhodecode/controllers/admin/permissions.py:72 -#: rhodecode/controllers/admin/permissions.py:83 -#: rhodecode/controllers/admin/permissions.py:86 -#: rhodecode/controllers/admin/permissions.py:89 -#: rhodecode/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:87 +#: kallithea/controllers/admin/permissions.py:92 +#: kallithea/controllers/admin/permissions.py:95 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 msgid "Disabled" msgstr "停用" -#: rhodecode/controllers/admin/permissions.py:74 +#: kallithea/controllers/admin/permissions.py:78 msgid "Allowed with manual account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:76 +#: kallithea/controllers/admin/permissions.py:80 msgid "Allowed with automatic account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:79 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1439 rhodecode/model/db.py:1444 +#: kallithea/controllers/admin/permissions.py:83 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1487 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1566 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1605 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1657 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1684 kallithea/model/db.py:1694 msgid "Manual activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:80 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1440 rhodecode/model/db.py:1445 +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1488 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1567 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1606 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1658 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1685 kallithea/model/db.py:1695 msgid "Automatic activation of external account" msgstr "" -#: rhodecode/controllers/admin/permissions.py:84 -#: rhodecode/controllers/admin/permissions.py:87 -#: rhodecode/controllers/admin/permissions.py:90 -#: rhodecode/controllers/admin/permissions.py:93 +#: kallithea/controllers/admin/permissions.py:88 +#: kallithea/controllers/admin/permissions.py:91 +#: kallithea/controllers/admin/permissions.py:96 +#: kallithea/controllers/admin/permissions.py:99 +#: kallithea/controllers/admin/permissions.py:102 msgid "Enabled" msgstr "啟用" -#: rhodecode/controllers/admin/permissions.py:138 -msgid "Default permissions updated successfully" -msgstr "預設權限更新完成" - -#: rhodecode/controllers/admin/permissions.py:152 +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:139 msgid "Error occurred during update of permissions" msgstr "" -#: rhodecode/controllers/admin/repos.py:128 -msgid "--REMOVE FORK--" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:168 +#: kallithea/controllers/admin/repo_groups.py:186 +#, python-format +msgid "Created repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:198 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:256 +#, python-format +msgid "Updated repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:271 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:289 +#, python-format +msgid "This group contains %s repositores and cannot be deleted" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:296 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:302 +#, python-format +msgid "Removed repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:307 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:419 +#: kallithea/controllers/admin/repo_groups.py:454 +#: kallithea/controllers/admin/user_groups.py:337 +msgid "Cannot revoke permission for yourself as admin" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:434 +msgid "Repository Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:471 +#: kallithea/controllers/admin/repos.py:426 +#: kallithea/controllers/admin/user_groups.py:349 +msgid "An error occurred during revoking of permission" +msgstr "" + +#: kallithea/controllers/admin/repos.py:162 +#, python-format +msgid "Error creating repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:237 #, python-format msgid "Created repository %s from %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:174 +#: kallithea/controllers/admin/repos.py:246 +#, python-format +msgid "Forked repository %s as %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:249 #, python-format msgid "Created repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:197 -#, python-format -msgid "Error creating repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:270 +#: kallithea/controllers/admin/repos.py:289 #, python-format msgid "Repository %s updated successfully" msgstr "版本庫 %s 更新完成" -#: rhodecode/controllers/admin/repos.py:288 +#: kallithea/controllers/admin/repos.py:307 #, python-format msgid "Error occurred during update of repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:315 +#: kallithea/controllers/admin/repos.py:334 #, python-format msgid "Detached %s forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:318 +#: kallithea/controllers/admin/repos.py:337 #, python-format msgid "Deleted %s forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:323 +#: kallithea/controllers/admin/repos.py:342 #, python-format msgid "Deleted repository %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:326 +#: kallithea/controllers/admin/repos.py:345 #, python-format msgid "Cannot delete %s it still contains attached forks" msgstr "" -#: rhodecode/controllers/admin/repos.py:331 +#: kallithea/controllers/admin/repos.py:350 #, python-format msgid "An error occurred during deletion of %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:345 +#: kallithea/controllers/admin/repos.py:402 msgid "Repository permissions updated" msgstr "" -#: rhodecode/controllers/admin/repos.py:375 -#: rhodecode/controllers/admin/repos_groups.py:332 -#: rhodecode/controllers/admin/users_groups.py:312 -msgid "An error occurred during revoking of permission" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:392 -msgid "An error occurred during deletion of repository stats" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:409 -msgid "An error occurred during cache invalidation" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:429 -#: rhodecode/controllers/admin/repos.py:456 -msgid "An error occurred during unlocking" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:447 -msgid "Unlocked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:450 -msgid "Locked" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:452 -#, python-format -msgid "Repository has been %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:476 +#: kallithea/controllers/admin/repos.py:458 +msgid "An error occurred during creation of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:472 +msgid "An error occurred during removal of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:488 +msgid "-- Not a fork --" +msgstr "" + +#: kallithea/controllers/admin/repos.py:522 msgid "Updated repository visibility in public journal" msgstr "" -#: rhodecode/controllers/admin/repos.py:480 +#: kallithea/controllers/admin/repos.py:526 msgid "An error occurred during setting this repository in public journal" msgstr "" -#: rhodecode/controllers/admin/repos.py:485 rhodecode/model/validators.py:302 +#: kallithea/controllers/admin/repos.py:531 kallithea/model/validators.py:359 msgid "Token mismatch" msgstr "" -#: rhodecode/controllers/admin/repos.py:498 -msgid "Pulled from remote location" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:501 -msgid "An error occurred during pull from remote location" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:517 +#: kallithea/controllers/admin/repos.py:546 msgid "Nothing" msgstr "" -#: rhodecode/controllers/admin/repos.py:519 +#: kallithea/controllers/admin/repos.py:548 #, python-format msgid "Marked repo %s as fork of %s" msgstr "" -#: rhodecode/controllers/admin/repos.py:523 +#: kallithea/controllers/admin/repos.py:555 msgid "An error occurred during this operation" msgstr "" -#: rhodecode/controllers/admin/repos.py:562 -msgid "An error occurred during creation of field" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:576 -msgid "An error occurred during removal of field" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:147 -#, python-format -msgid "Created repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:159 -#, python-format -msgid "Error occurred during creation of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:217 -#, python-format -msgid "Updated repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:232 -#, python-format -msgid "Error occurred during update of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:250 -#, python-format -msgid "This group contains %s repositores and cannot be deleted" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:257 -#, python-format -msgid "This group contains %s subgroups and cannot be deleted" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:263 -#, python-format -msgid "Removed repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:268 -#, python-format -msgid "Error occurred during deletion of repository group %s" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:279 -#: rhodecode/controllers/admin/repos_groups.py:314 -#: rhodecode/controllers/admin/users_groups.py:300 -msgid "Cannot revoke permission for yourself as admin" -msgstr "" - -#: rhodecode/controllers/admin/repos_groups.py:294 -msgid "Repository Group permissions updated" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:123 +#: kallithea/controllers/admin/repos.py:571 +msgid "Locked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:574 +msgid "Unlocked repository" +msgstr "" + +#: kallithea/controllers/admin/repos.py:577 +#: kallithea/controllers/admin/repos.py:604 +msgid "An error occurred during unlocking" +msgstr "" + +#: kallithea/controllers/admin/repos.py:595 +msgid "Unlocked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:598 +msgid "Locked" +msgstr "" + +#: kallithea/controllers/admin/repos.py:600 +#, python-format +msgid "Repository has been %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:618 +msgid "Cache invalidation successful" +msgstr "" + +#: kallithea/controllers/admin/repos.py:622 +msgid "An error occurred during cache invalidation" +msgstr "" + +#: kallithea/controllers/admin/repos.py:637 +msgid "Pulled from remote location" +msgstr "" + +#: kallithea/controllers/admin/repos.py:640 +msgid "An error occurred during pull from remote location" +msgstr "" + +#: kallithea/controllers/admin/repos.py:673 +msgid "An error occurred during deletion of repository stats" +msgstr "" + +#: kallithea/controllers/admin/settings.py:172 +msgid "Updated VCS settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:176 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:182 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:215 #, python-format msgid "Repositories successfully rescanned added: %s ; removed: %s" msgstr "" -#: rhodecode/controllers/admin/settings.py:132 +#: kallithea/controllers/admin/settings.py:270 +msgid "Updated application settings" +msgstr "更新應用設定" + +#: kallithea/controllers/admin/settings.py:327 +msgid "Updated visualisation settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:332 +msgid "Error occurred during updating visualisation settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:358 +msgid "Please enter email address" +msgstr "" + +#: kallithea/controllers/admin/settings.py:370 +msgid "Send email task created" +msgstr "" + +#: kallithea/controllers/admin/settings.py:400 +msgid "Added new hook" +msgstr "新增hook" + +#: kallithea/controllers/admin/settings.py:414 +msgid "Updated hooks" +msgstr "更新hook" + +#: kallithea/controllers/admin/settings.py:418 +msgid "Error occurred during hook creation" +msgstr "" + +#: kallithea/controllers/admin/settings.py:444 msgid "Whoosh reindex task scheduled" msgstr "Whoosh 重新索引工作排程" -#: rhodecode/controllers/admin/settings.py:163 -msgid "Updated application settings" -msgstr "更新應用設定" - -#: rhodecode/controllers/admin/settings.py:167 -#: rhodecode/controllers/admin/settings.py:304 -msgid "Error occurred during updating application settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:219 -msgid "Updated visualisation settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:224 -msgid "Error occurred during updating visualisation settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:300 -msgid "Updated VCS settings" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:314 -msgid "Added new hook" -msgstr "新增hook" - -#: rhodecode/controllers/admin/settings.py:326 -msgid "Updated hooks" -msgstr "更新hook" - -#: rhodecode/controllers/admin/settings.py:330 -msgid "Error occurred during hook creation" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:349 -msgid "Email task created" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:413 -msgid "You can't edit this user since it's crucial for entire application" -msgstr "" - -#: rhodecode/controllers/admin/settings.py:455 -msgid "Your account was updated successfully" -msgstr "您的帳號已更新完成" - -#: rhodecode/controllers/admin/settings.py:470 -#: rhodecode/controllers/admin/users.py:198 -#, python-format -msgid "Error occurred during update of user %s" -msgstr "" - -#: rhodecode/controllers/admin/users.py:130 +#: kallithea/controllers/admin/user_groups.py:150 +#, python-format +msgid "Created user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:161 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Updated user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:221 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:239 +msgid "Successfully deleted user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:244 +msgid "An error occurred during deletion of user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:311 +msgid "Target group cannot be the same" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:317 +msgid "User Group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:437 +#: kallithea/controllers/admin/users.py:397 +msgid "Updated permissions" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:441 +#: kallithea/controllers/admin/users.py:401 +msgid "An error occurred during permissions saving" +msgstr "" + +#: kallithea/controllers/admin/users.py:135 #, python-format msgid "Created user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:142 +#: kallithea/controllers/admin/users.py:149 #, python-format msgid "Error occurred during creation of user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:176 +#: kallithea/controllers/admin/users.py:188 msgid "User updated successfully" msgstr "使用者更新完成" -#: rhodecode/controllers/admin/users.py:214 +#: kallithea/controllers/admin/users.py:223 msgid "Successfully deleted user" msgstr "" -#: rhodecode/controllers/admin/users.py:219 +#: kallithea/controllers/admin/users.py:228 msgid "An error occurred during deletion of user" msgstr "" -#: rhodecode/controllers/admin/users.py:234 +#: kallithea/controllers/admin/users.py:242 +#: kallithea/controllers/admin/users.py:260 +#: kallithea/controllers/admin/users.py:283 +#: kallithea/controllers/admin/users.py:308 +#: kallithea/controllers/admin/users.py:321 +#: kallithea/controllers/admin/users.py:345 +#: kallithea/controllers/admin/users.py:408 +#: kallithea/controllers/admin/users.py:455 msgid "You can't edit this user" msgstr "您無法編輯這位使用者" -#: rhodecode/controllers/admin/users.py:293 -#: rhodecode/controllers/admin/users_groups.py:372 -msgid "Updated permissions" -msgstr "" - -#: rhodecode/controllers/admin/users.py:297 -#: rhodecode/controllers/admin/users_groups.py:376 -msgid "An error occurred during permissions saving" -msgstr "" - -#: rhodecode/controllers/admin/users.py:311 -#, python-format -msgid "Added email %s to user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:317 -msgid "An error occurred during email saving" -msgstr "" - -#: rhodecode/controllers/admin/users.py:327 -msgid "Removed email from user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:340 -#, python-format -msgid "Added ip %s to user" -msgstr "" - -#: rhodecode/controllers/admin/users.py:346 +#: kallithea/controllers/admin/users.py:483 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "" + +#: kallithea/controllers/admin/users.py:489 msgid "An error occurred during ip saving" msgstr "" -#: rhodecode/controllers/admin/users.py:358 -msgid "Removed ip from user" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:162 -#, python-format -msgid "Created user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:173 -#, python-format -msgid "Error occurred during creation of user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:210 -#, python-format -msgid "Updated user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:232 -#, python-format -msgid "Error occurred during update of user group %s" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:250 -msgid "Successfully deleted user group" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:255 -msgid "An error occurred during deletion of user group" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:274 -msgid "Target group cannot be the same" -msgstr "" - -#: rhodecode/controllers/admin/users_groups.py:280 -msgid "User Group permissions updated" -msgstr "" - -#: rhodecode/lib/auth.py:544 +#: kallithea/controllers/admin/users.py:503 +msgid "Removed ip address from user whitelist" +msgstr "" + +#: kallithea/lib/auth.py:748 #, python-format msgid "IP %s not allowed" msgstr "" -#: rhodecode/lib/auth.py:593 +#: kallithea/lib/auth.py:809 msgid "You need to be a registered user to perform this action" msgstr "您必須是註冊使用者才能執行這個動作" -#: rhodecode/lib/auth.py:634 +#: kallithea/lib/auth.py:846 msgid "You need to be a signed in to view this page" msgstr "您必須登入後才能瀏覽這個頁面" -#: rhodecode/lib/diffs.py:66 +#: kallithea/lib/diffs.py:66 msgid "Binary file" msgstr "" -#: rhodecode/lib/diffs.py:82 -msgid "" -"Changeset was too big and was cut off, use diff menu to display this diff" -msgstr "" - -#: rhodecode/lib/diffs.py:92 +#: kallithea/lib/diffs.py:82 +msgid "Changeset was too big and was cut off, use diff menu to display this diff" +msgstr "" + +#: kallithea/lib/diffs.py:92 msgid "No changes detected" msgstr "尚未有任何變更" -#: rhodecode/lib/helpers.py:539 -msgid "True" -msgstr "真" - -#: rhodecode/lib/helpers.py:542 -msgid "False" -msgstr "假" - -#: rhodecode/lib/helpers.py:580 +#: kallithea/lib/helpers.py:598 #, python-format msgid "Deleted branch: %s" msgstr "" -#: rhodecode/lib/helpers.py:583 +#: kallithea/lib/helpers.py:601 #, python-format msgid "Created tag: %s" msgstr "" -#: rhodecode/lib/helpers.py:596 +#: kallithea/lib/helpers.py:614 msgid "Changeset not found" msgstr "" -#: rhodecode/lib/helpers.py:646 +#: kallithea/lib/helpers.py:664 #, python-format msgid "Show all combined changesets %s->%s" msgstr "" -#: rhodecode/lib/helpers.py:652 +#: kallithea/lib/helpers.py:670 msgid "compare view" msgstr "" -#: rhodecode/lib/helpers.py:672 +#: kallithea/lib/helpers.py:690 msgid "and" msgstr "和" -#: rhodecode/lib/helpers.py:673 +#: kallithea/lib/helpers.py:691 #, python-format msgid "%s more" msgstr "" -#: rhodecode/lib/helpers.py:674 -#: rhodecode/templates/changelog/changelog.html:53 +#: kallithea/lib/helpers.py:692 kallithea/templates/changelog/changelog.html:58 msgid "revisions" msgstr "修訂" -#: rhodecode/lib/helpers.py:698 +#: kallithea/lib/helpers.py:716 #, python-format msgid "fork name %s" msgstr "" -#: rhodecode/lib/helpers.py:715 -#: rhodecode/templates/pullrequests/pullrequest_show.html:8 +#: kallithea/lib/helpers.py:733 +#: kallithea/templates/pullrequests/pullrequest_show.html:11 #, python-format msgid "Pull request #%s" msgstr "" -#: rhodecode/lib/helpers.py:725 +#: kallithea/lib/helpers.py:743 msgid "[deleted] repository" msgstr "" -#: rhodecode/lib/helpers.py:727 rhodecode/lib/helpers.py:739 +#: kallithea/lib/helpers.py:745 kallithea/lib/helpers.py:757 msgid "[created] repository" msgstr "" -#: rhodecode/lib/helpers.py:729 +#: kallithea/lib/helpers.py:747 msgid "[created] repository as fork" msgstr "" -#: rhodecode/lib/helpers.py:731 rhodecode/lib/helpers.py:741 +#: kallithea/lib/helpers.py:749 kallithea/lib/helpers.py:759 msgid "[forked] repository" msgstr "" -#: rhodecode/lib/helpers.py:733 rhodecode/lib/helpers.py:743 +#: kallithea/lib/helpers.py:751 kallithea/lib/helpers.py:761 msgid "[updated] repository" msgstr "" -#: rhodecode/lib/helpers.py:735 +#: kallithea/lib/helpers.py:753 msgid "[downloaded] archive from repository" msgstr "" -#: rhodecode/lib/helpers.py:737 +#: kallithea/lib/helpers.py:755 msgid "[delete] repository" msgstr "" -#: rhodecode/lib/helpers.py:745 +#: kallithea/lib/helpers.py:763 msgid "[created] user" msgstr "" -#: rhodecode/lib/helpers.py:747 +#: kallithea/lib/helpers.py:765 msgid "[updated] user" msgstr "" -#: rhodecode/lib/helpers.py:749 +#: kallithea/lib/helpers.py:767 msgid "[created] user group" msgstr "" -#: rhodecode/lib/helpers.py:751 +#: kallithea/lib/helpers.py:769 msgid "[updated] user group" msgstr "" -#: rhodecode/lib/helpers.py:753 +#: kallithea/lib/helpers.py:771 msgid "[commented] on revision in repository" msgstr "" -#: rhodecode/lib/helpers.py:755 +#: kallithea/lib/helpers.py:773 msgid "[commented] on pull request for" msgstr "" -#: rhodecode/lib/helpers.py:757 +#: kallithea/lib/helpers.py:775 msgid "[closed] pull request for" msgstr "" -#: rhodecode/lib/helpers.py:759 +#: kallithea/lib/helpers.py:777 msgid "[pushed] into" msgstr "" -#: rhodecode/lib/helpers.py:761 -msgid "[committed via RhodeCode] into repository" -msgstr "" - -#: rhodecode/lib/helpers.py:763 +#: kallithea/lib/helpers.py:779 +msgid "[committed via Kallithea] into repository" +msgstr "" + +#: kallithea/lib/helpers.py:781 msgid "[pulled from remote] into repository" msgstr "" -#: rhodecode/lib/helpers.py:765 +#: kallithea/lib/helpers.py:783 msgid "[pulled] from" msgstr "" -#: rhodecode/lib/helpers.py:767 +#: kallithea/lib/helpers.py:785 msgid "[started following] repository" msgstr "" -#: rhodecode/lib/helpers.py:769 +#: kallithea/lib/helpers.py:787 msgid "[stopped following] repository" msgstr "" -#: rhodecode/lib/helpers.py:1088 +#: kallithea/lib/helpers.py:1101 #, python-format msgid " and %s more" msgstr "" -#: rhodecode/lib/helpers.py:1092 +#: kallithea/lib/helpers.py:1105 msgid "No Files" msgstr "沒有檔案" -#: rhodecode/lib/helpers.py:1158 +#: kallithea/lib/helpers.py:1171 msgid "new file" msgstr "" -#: rhodecode/lib/helpers.py:1161 +#: kallithea/lib/helpers.py:1174 msgid "mod" msgstr "" -#: rhodecode/lib/helpers.py:1164 +#: kallithea/lib/helpers.py:1177 msgid "del" msgstr "" -#: rhodecode/lib/helpers.py:1167 +#: kallithea/lib/helpers.py:1180 msgid "rename" msgstr "" -#: rhodecode/lib/helpers.py:1172 +#: kallithea/lib/helpers.py:1185 msgid "chmod" msgstr "" -#: rhodecode/lib/helpers.py:1404 +#: kallithea/lib/helpers.py:1417 #, python-format msgid "" -"%s repository is not mapped to db perhaps it was created or renamed from the" -" filesystem please run the application again in order to rescan repositories" -msgstr "" - -#: rhodecode/lib/unionrepo.py:193 -msgid "cannot create new union repository" -msgstr "" - -#: rhodecode/lib/utils2.py:410 +"%s repository is not mapped to db perhaps it was created or renamed from " +"the filesystem please run the application again in order to rescan " +"repositories" +msgstr "" + +#: kallithea/lib/utils2.py:415 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" -#: rhodecode/lib/utils2.py:411 +#: kallithea/lib/utils2.py:416 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" -#: rhodecode/lib/utils2.py:412 +#: kallithea/lib/utils2.py:417 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" -#: rhodecode/lib/utils2.py:413 +#: kallithea/lib/utils2.py:418 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" -#: rhodecode/lib/utils2.py:414 +#: kallithea/lib/utils2.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" -#: rhodecode/lib/utils2.py:415 +#: kallithea/lib/utils2.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" -#: rhodecode/lib/utils2.py:431 +#: kallithea/lib/utils2.py:436 #, python-format msgid "in %s" msgstr "" -#: rhodecode/lib/utils2.py:433 +#: kallithea/lib/utils2.py:438 #, python-format msgid "%s ago" msgstr "" -#: rhodecode/lib/utils2.py:435 +#: kallithea/lib/utils2.py:440 #, python-format msgid "in %s and %s" msgstr "" -#: rhodecode/lib/utils2.py:438 +#: kallithea/lib/utils2.py:443 #, python-format msgid "%s and %s ago" msgstr "" -#: rhodecode/lib/utils2.py:441 +#: kallithea/lib/utils2.py:446 msgid "just now" msgstr "現在" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1163 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1183 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1303 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1388 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1408 rhodecode/model/db.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1166 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1305 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1390 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1410 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1456 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1574 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1651 kallithea/model/db.py:1661 msgid "Repository no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1164 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1184 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1304 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1389 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1409 rhodecode/model/db.py:1414 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1167 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1186 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1306 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1391 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1411 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1457 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1514 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1575 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1652 kallithea/model/db.py:1662 msgid "Repository read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1165 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1185 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1305 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1390 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1410 rhodecode/model/db.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1168 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1187 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1307 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1392 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1412 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1458 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1515 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1576 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1653 kallithea/model/db.py:1663 msgid "Repository write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1166 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1186 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1306 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1391 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1411 rhodecode/model/db.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1169 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1188 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1393 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1413 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1459 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1516 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1577 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1654 kallithea/model/db.py:1664 msgid "Repository admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1168 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1188 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1308 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1171 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1190 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 msgid "Repositories Group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1169 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1189 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1309 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1172 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1191 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1311 msgid "Repositories Group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1170 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1190 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1310 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1173 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1192 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1312 msgid "Repositories Group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1171 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1191 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1311 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1174 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1193 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1313 msgid "Repositories Group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1173 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1193 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1313 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1398 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1406 rhodecode/model/db.py:1411 -msgid "RhodeCode Administrator" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1174 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1194 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1314 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1399 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1429 rhodecode/model/db.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1176 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1195 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1315 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1400 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1408 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1454 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1511 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1572 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1622 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1649 kallithea/model/db.py:1659 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1177 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1196 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1477 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1556 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1595 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1682 msgid "Repository creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1175 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1195 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1315 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1400 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1430 rhodecode/model/db.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1178 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1197 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1478 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1535 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1557 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1596 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1683 msgid "Repository creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1176 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1196 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1316 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1401 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1432 rhodecode/model/db.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1179 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1198 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1434 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1480 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1559 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1598 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1677 kallithea/model/db.py:1687 msgid "Repository forking disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1177 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1197 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1317 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1402 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1433 rhodecode/model/db.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1180 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1199 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1435 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1481 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1538 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1560 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1599 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1678 kallithea/model/db.py:1688 msgid "Repository forking enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1178 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1198 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1318 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1403 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1181 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1200 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1320 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1405 msgid "Register disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1179 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1199 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1319 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1404 -msgid "Register new user with RhodeCode with manual activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1182 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1202 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1322 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1407 -msgid "Register new user with RhodeCode with auto activation" -msgstr "" - -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1623 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1643 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1763 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1838 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1934 rhodecode/model/db.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1201 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1321 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1406 +msgid "Register new user with Kallithea with manual activation" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1185 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1204 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1324 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1409 +msgid "Register new user with Kallithea with auto activation" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1626 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1765 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1840 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1936 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1982 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2064 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2103 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2156 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2202 kallithea/model/db.py:2212 msgid "Not Reviewed" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1624 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1644 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1764 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1839 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1935 rhodecode/model/db.py:1940 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1627 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1766 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1841 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1937 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1983 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2043 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2065 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2104 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2157 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2203 kallithea/model/db.py:2213 msgid "Approved" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1625 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1645 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1765 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1840 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1936 rhodecode/model/db.py:1941 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1767 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1842 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1938 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1984 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2044 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2066 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2105 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2158 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2204 kallithea/model/db.py:2214 msgid "Rejected" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_4_0.py:1626 -#: rhodecode/lib/dbmigrate/schema/db_1_5_0.py:1646 -#: rhodecode/lib/dbmigrate/schema/db_1_5_2.py:1766 -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1841 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1937 rhodecode/model/db.py:1942 +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1768 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1843 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1939 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1985 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2045 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2046 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2067 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2106 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2159 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2205 kallithea/model/db.py:2215 msgid "Under Review" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1252 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1270 rhodecode/model/db.py:1275 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1254 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1272 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1302 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1359 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1360 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1381 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1500 kallithea/model/db.py:1510 msgid "top level" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1393 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1413 rhodecode/model/db.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1395 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1415 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1461 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1579 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1629 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1656 kallithea/model/db.py:1666 msgid "Repository group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1394 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1414 rhodecode/model/db.py:1419 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1396 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1416 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1462 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1519 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1580 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1630 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1657 kallithea/model/db.py:1667 msgid "Repository group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1395 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1415 rhodecode/model/db.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1397 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1417 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1463 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1520 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1581 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1631 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1658 kallithea/model/db.py:1668 msgid "Repository group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_6_0.py:1396 -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1416 rhodecode/model/db.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1464 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1521 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1582 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1632 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1659 kallithea/model/db.py:1669 msgid "Repository group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1418 rhodecode/model/db.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1420 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1466 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1545 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1584 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1634 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1661 kallithea/model/db.py:1671 msgid "User group no access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1419 rhodecode/model/db.py:1424 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1421 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1467 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1524 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1546 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1585 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1635 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1662 kallithea/model/db.py:1672 msgid "User group read access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1420 rhodecode/model/db.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1422 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1468 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1525 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1547 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1586 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1636 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1663 kallithea/model/db.py:1673 msgid "User group write access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1421 rhodecode/model/db.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1423 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1469 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1526 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1548 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1587 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1637 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1664 kallithea/model/db.py:1674 msgid "User group admin access" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1423 rhodecode/model/db.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1425 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1550 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1589 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1639 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1666 kallithea/model/db.py:1676 msgid "Repository Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1424 rhodecode/model/db.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1426 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1472 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1529 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1551 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1590 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1640 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1667 kallithea/model/db.py:1677 msgid "Repository Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1426 rhodecode/model/db.py:1431 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1428 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1474 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1553 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1592 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1642 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1669 kallithea/model/db.py:1679 msgid "User Group creation disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1427 rhodecode/model/db.py:1432 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1429 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1475 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1532 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1554 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1593 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1643 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1670 kallithea/model/db.py:1680 msgid "User Group creation enabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1435 rhodecode/model/db.py:1440 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1437 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1483 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1562 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1601 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1653 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1680 kallithea/model/db.py:1690 msgid "Registration disabled" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1436 rhodecode/model/db.py:1441 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1438 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1484 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1541 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1563 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1602 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1654 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1681 kallithea/model/db.py:1691 msgid "User Registration with manual account activation" msgstr "" -#: rhodecode/lib/dbmigrate/schema/db_1_7_0.py:1437 rhodecode/model/db.py:1442 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1439 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1485 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1542 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1564 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1603 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1655 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1682 kallithea/model/db.py:1692 msgid "User Registration with automatic account activation" msgstr "" -#: rhodecode/model/comment.py:75 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1647 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1674 kallithea/model/db.py:1684 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1685 +msgid "Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:77 #, python-format msgid "on line %s" msgstr "" -#: rhodecode/model/comment.py:220 +#: kallithea/model/comment.py:222 msgid "[Mention]" msgstr "" -#: rhodecode/model/forms.py:43 +#: kallithea/model/forms.py:57 msgid "Please enter a login" msgstr "請登入" -#: rhodecode/model/forms.py:44 +#: kallithea/model/forms.py:58 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "" -#: rhodecode/model/forms.py:52 +#: kallithea/model/forms.py:66 msgid "Please enter a password" msgstr "請輸入密碼" -#: rhodecode/model/forms.py:53 +#: kallithea/model/forms.py:67 #, python-format msgid "Enter %(min)i characters or more" msgstr "" -#: rhodecode/model/notification.py:228 +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:231 #, python-format msgid "%(user)s commented on changeset at %(when)s" msgstr "" -#: rhodecode/model/notification.py:229 +#: kallithea/model/notification.py:232 #, python-format msgid "%(user)s sent message at %(when)s" msgstr "" -#: rhodecode/model/notification.py:230 +#: kallithea/model/notification.py:233 #, python-format msgid "%(user)s mentioned you at %(when)s" msgstr "" -#: rhodecode/model/notification.py:231 -#, python-format -msgid "%(user)s registered in RhodeCode at %(when)s" -msgstr "" - -#: rhodecode/model/notification.py:232 +#: kallithea/model/notification.py:234 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "" + +#: kallithea/model/notification.py:235 #, python-format msgid "%(user)s opened new pull request at %(when)s" msgstr "" -#: rhodecode/model/notification.py:233 +#: kallithea/model/notification.py:236 #, python-format msgid "%(user)s commented on pull request at %(when)s" msgstr "" -#: rhodecode/model/pull_request.py:98 +#: kallithea/model/pull_request.py:107 #, python-format msgid "%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s" msgstr "" -#: rhodecode/model/scm.py:674 +#: kallithea/model/scm.py:810 msgid "latest tip" msgstr "" -#: rhodecode/model/user.py:232 +#: kallithea/model/user.py:198 msgid "New user registration" msgstr "" -#: rhodecode/model/user.py:257 rhodecode/model/user.py:281 +#: kallithea/model/user.py:222 kallithea/model/user.py:247 msgid "You can't Edit this user since it's crucial for entire application" msgstr "您無法編輯這個使用者,因為他是系統帳號" -#: rhodecode/model/user.py:303 +#: kallithea/model/user.py:270 msgid "You can't remove this user since it's crucial for entire application" msgstr "您無法移除這個使用者,因為他是系統帳號" -#: rhodecode/model/user.py:309 +#: kallithea/model/user.py:276 #, python-format msgid "" -"user \"%s\" still owns %s repositories and cannot be removed. Switch owners " -"or remove those repositories. %s" -msgstr "" - -#: rhodecode/model/user.py:334 +"user \"%s\" still owns %s repositories and cannot be removed. Switch " +"owners or remove those repositories. %s" +msgstr "" + +#: kallithea/model/user.py:304 msgid "Password reset link" msgstr "" -#: rhodecode/model/user.py:366 +#: kallithea/model/user.py:333 msgid "Your new password" msgstr "" -#: rhodecode/model/user.py:367 -#, python-format -msgid "Your new RhodeCode password:%s" -msgstr "" - -#: rhodecode/model/validators.py:38 rhodecode/model/validators.py:39 +#: kallithea/model/user.py:334 +#, python-format +msgid "Your new Kallithea password:%s" +msgstr "" + +#: kallithea/model/validators.py:82 kallithea/model/validators.py:83 msgid "Value cannot be an empty list" msgstr "" -#: rhodecode/model/validators.py:85 +#: kallithea/model/validators.py:120 #, python-format msgid "Username \"%(username)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:87 +#: kallithea/model/validators.py:122 #, python-format msgid "Username \"%(username)s\" is forbidden" msgstr "" -#: rhodecode/model/validators.py:89 +#: kallithea/model/validators.py:124 msgid "" -"Username may only contain alphanumeric characters underscores, periods or " -"dashes and must begin with alphanumeric character or underscore" -msgstr "" - -#: rhodecode/model/validators.py:117 +"Username may only contain alphanumeric characters underscores, periods or" +" dashes and must begin with alphanumeric character or underscore" +msgstr "" + +#: kallithea/model/validators.py:151 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:158 #, python-format msgid "Username %(username)s is not valid" msgstr "" -#: rhodecode/model/validators.py:136 +#: kallithea/model/validators.py:177 msgid "Invalid user group name" msgstr "" -#: rhodecode/model/validators.py:137 +#: kallithea/model/validators.py:178 #, python-format msgid "User group \"%(usergroup)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:139 +#: kallithea/model/validators.py:180 msgid "" "user group name may only contain alphanumeric characters underscores, " "periods or dashes and must begin with alphanumeric character" msgstr "" -#: rhodecode/model/validators.py:177 +#: kallithea/model/validators.py:218 msgid "Cannot assign this group as parent" msgstr "" -#: rhodecode/model/validators.py:178 +#: kallithea/model/validators.py:219 #, python-format msgid "Group \"%(group_name)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:180 +#: kallithea/model/validators.py:221 #, python-format msgid "Repository with name \"%(group_name)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:238 +#: kallithea/model/validators.py:279 msgid "Invalid characters (non-ascii) in password" msgstr "" -#: rhodecode/model/validators.py:253 +#: kallithea/model/validators.py:294 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:310 msgid "Passwords do not match" msgstr "密碼不相符" -#: rhodecode/model/validators.py:270 +#: kallithea/model/validators.py:327 msgid "invalid password" msgstr "無效的密碼" -#: rhodecode/model/validators.py:271 +#: kallithea/model/validators.py:328 msgid "invalid user name" msgstr "無效的使用者名稱" -#: rhodecode/model/validators.py:272 +#: kallithea/model/validators.py:329 msgid "Your account is disabled" msgstr "您的帳號已被停用" -#: rhodecode/model/validators.py:316 +#: kallithea/model/validators.py:373 #, python-format msgid "Repository name %(repo)s is disallowed" msgstr "" -#: rhodecode/model/validators.py:318 +#: kallithea/model/validators.py:375 #, python-format msgid "Repository named %(repo)s already exists" msgstr "" -#: rhodecode/model/validators.py:319 +#: kallithea/model/validators.py:376 #, python-format msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" msgstr "" -#: rhodecode/model/validators.py:321 +#: kallithea/model/validators.py:378 #, python-format msgid "Repository group with name \"%(repo)s\" already exists" msgstr "" -#: rhodecode/model/validators.py:438 +#: kallithea/model/validators.py:493 msgid "invalid clone url" msgstr "無效的複製URL" -#: rhodecode/model/validators.py:439 +#: kallithea/model/validators.py:494 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url" msgstr "" -#: rhodecode/model/validators.py:464 +#: kallithea/model/validators.py:519 msgid "Fork have to be the same type as parent" msgstr "" -#: rhodecode/model/validators.py:479 +#: kallithea/model/validators.py:534 msgid "You don't have permissions to create repository in this group" msgstr "" -#: rhodecode/model/validators.py:481 +#: kallithea/model/validators.py:536 msgid "no permission to create repository in root location" msgstr "" -#: rhodecode/model/validators.py:518 +#: kallithea/model/validators.py:585 msgid "You don't have permissions to create a group in this location" msgstr "" -#: rhodecode/model/validators.py:559 +#: kallithea/model/validators.py:626 msgid "This username or user group name is not valid" msgstr "" -#: rhodecode/model/validators.py:652 +#: kallithea/model/validators.py:719 msgid "This is not a valid path" msgstr "不是一個有效的路徑" -#: rhodecode/model/validators.py:667 +#: kallithea/model/validators.py:734 msgid "This e-mail address is already taken" msgstr "這個郵件位址已經使用了" -#: rhodecode/model/validators.py:687 +#: kallithea/model/validators.py:754 #, python-format msgid "e-mail \"%(email)s\" does not exist." msgstr "" -#: rhodecode/model/validators.py:724 +#: kallithea/model/validators.py:791 msgid "" -"The LDAP Login attribute of the CN must be specified - this is the name of " -"the attribute that is equivalent to \"username\"" -msgstr "" - -#: rhodecode/model/validators.py:737 +"The LDAP Login attribute of the CN must be specified - this is the name " +"of the attribute that is equivalent to \"username\"" +msgstr "" + +#: kallithea/model/validators.py:804 #, python-format msgid "Revisions %(revs)s are already part of pull request or have set status" msgstr "" -#: rhodecode/model/validators.py:769 +#: kallithea/model/validators.py:836 msgid "Please enter a valid IPv4 or IpV6 address" msgstr "" -#: rhodecode/model/validators.py:770 -#, python-format -msgid "" -"The network size (bits) must be within the range of 0-32 (not %(bits)r)" -msgstr "" - -#: rhodecode/model/validators.py:803 +#: kallithea/model/validators.py:837 +#, python-format +msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)" +msgstr "" + +#: kallithea/model/validators.py:870 msgid "Key name can only consist of letters, underscore, dash or numbers" msgstr "" -#: rhodecode/model/validators.py:817 +#: kallithea/model/validators.py:884 msgid "Filename cannot be inside a directory" msgstr "" -#: rhodecode/templates/index.html:5 +#: kallithea/model/validators.py:900 +#, python-format +msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name" +msgstr "" + +#: kallithea/templates/about.html:4 kallithea/templates/about.html:20 +msgid "About" +msgstr "" + +#: kallithea/templates/index.html:5 msgid "Dashboard" msgstr "儀表板" -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/repo_switcher_list.html:4 -#: rhodecode/templates/admin/repos/repos.html:9 -#: rhodecode/templates/admin/users/user_edit_my_account.html:31 -#: rhodecode/templates/admin/users/users.html:9 -#: rhodecode/templates/bookmarks/bookmarks.html:9 -#: rhodecode/templates/branches/branches.html:9 -#: rhodecode/templates/journal/journal.html:9 -#: rhodecode/templates/journal/journal.html:46 -#: rhodecode/templates/journal/journal.html:47 -#: rhodecode/templates/tags/tags.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:3 +#: kallithea/templates/admin/my_account/my_account_watched.html:3 +#: kallithea/templates/admin/repo_groups/repo_groups.html:12 +#: kallithea/templates/admin/repos/repos.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:12 +#: kallithea/templates/admin/users/users.html:12 +#: kallithea/templates/bookmarks/bookmarks.html:12 +#: kallithea/templates/branches/branches.html:12 +#: kallithea/templates/journal/journal.html:12 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/journal/journal.html:50 +#: kallithea/templates/tags/tags.html:12 msgid "quick filter..." msgstr "快速過濾..." -#: rhodecode/templates/index_base.html:6 -#: rhodecode/templates/admin/repos/repos.html:9 +#: kallithea/templates/index_base.html:6 +#: kallithea/templates/admin/repos/repos.html:12 msgid "repositories" msgstr "個版本庫" -#: rhodecode/templates/index_base.html:13 -#: rhodecode/templates/index_base.html:18 -#: rhodecode/templates/admin/repos/repo_add.html:5 -#: rhodecode/templates/admin/repos/repos.html:22 -msgid "Add repository" -msgstr "新增版本庫" - -#: rhodecode/templates/index_base.html:15 -#: rhodecode/templates/index_base.html:20 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:31 -msgid "Add group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 -msgid "Edit group" -msgstr "" - -#: rhodecode/templates/index_base.html:27 +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:22 +#: kallithea/templates/admin/repos/repos.html:25 +msgid "Add Repository" +msgstr "" + +#: kallithea/templates/index_base.html:22 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:16 +#: kallithea/templates/admin/repo_groups/repo_groups.html:29 +msgid "Add Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:32 msgid "You have admin right to this group, and can edit it" msgstr "" -#: rhodecode/templates/index_base.html:40 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:33 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:38 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:43 -#: rhodecode/templates/admin/users_groups/users_group_add.html:32 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 -#: rhodecode/templates/admin/users_groups/users_groups.html:37 -msgid "Group name" -msgstr "群組名稱" - -#: rhodecode/templates/index_base.html:41 -#: rhodecode/templates/index_base.html:123 -#: rhodecode/templates/admin/repos/repo_add_base.html:56 -#: rhodecode/templates/admin/repos/repo_edit.html:68 -#: rhodecode/templates/admin/repos/repos.html:75 -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:42 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:47 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:44 -#: rhodecode/templates/email_templates/changeset_comment.html:9 -#: rhodecode/templates/email_templates/pull_request.html:9 -#: rhodecode/templates/forks/fork.html:56 -#: rhodecode/templates/pullrequests/pullrequest.html:43 -#: rhodecode/templates/pullrequests/pullrequest_show.html:81 -#: rhodecode/templates/summary/summary.html:106 +#: kallithea/templates/index_base.html:32 +msgid "Edit Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:45 +msgid "Group Name" +msgstr "" + +#: kallithea/templates/index_base.html:46 +#: kallithea/templates/index_base.html:128 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:45 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:51 +#: kallithea/templates/admin/user_groups/user_group_add.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:16 +#: kallithea/templates/email_templates/pull_request.html:9 +#: kallithea/templates/forks/fork.html:41 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +#: kallithea/templates/summary/summary.html:88 msgid "Description" msgstr "描述" -#: rhodecode/templates/index_base.html:51 -#: rhodecode/templates/admin/permissions/permissions.html:55 -#: rhodecode/templates/admin/repos/repo_add_base.html:29 -#: rhodecode/templates/admin/repos/repo_edit.html:50 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:57 -#: rhodecode/templates/forks/fork.html:47 -msgid "Repository group" -msgstr "版本庫群組" - -#: rhodecode/templates/index_base.html:121 -#: rhodecode/templates/admin/repos/repo_add_base.html:9 -#: rhodecode/templates/admin/repos/repo_edit.html:32 -#: rhodecode/templates/admin/repos/repos.html:73 -#: rhodecode/templates/admin/users/user_edit_my_account.html:172 -#: rhodecode/templates/base/perms_summary.html:37 -#: rhodecode/templates/bookmarks/bookmarks.html:48 -#: rhodecode/templates/bookmarks/bookmarks_data.html:6 -#: rhodecode/templates/branches/branches.html:47 -#: rhodecode/templates/branches/branches_data.html:6 -#: rhodecode/templates/files/files_browser.html:47 -#: rhodecode/templates/journal/journal.html:193 -#: rhodecode/templates/journal/journal.html:283 -#: rhodecode/templates/summary/summary.html:55 -#: rhodecode/templates/summary/summary.html:124 -#: rhodecode/templates/tags/tags.html:48 -#: rhodecode/templates/tags/tags_data.html:6 +#: kallithea/templates/index_base.html:126 +#: kallithea/templates/admin/my_account/my_account_repos.html:46 +#: kallithea/templates/admin/my_account/my_account_watched.html:46 +#: kallithea/templates/admin/repo_groups/repo_groups.html:50 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:50 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:41 +#: kallithea/templates/journal/journal.html:197 +#: kallithea/templates/journal/journal.html:288 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:7 msgid "Name" msgstr "名稱" -#: rhodecode/templates/index_base.html:124 +#: kallithea/templates/index_base.html:129 msgid "Last Change" msgstr "" -#: rhodecode/templates/index_base.html:126 -#: rhodecode/templates/admin/repos/repos.html:76 -#: rhodecode/templates/admin/users/user_edit_my_account.html:174 -#: rhodecode/templates/journal/journal.html:195 -#: rhodecode/templates/journal/journal.html:285 +#: kallithea/templates/index_base.html:131 +#: kallithea/templates/admin/my_account/my_account_repos.html:48 +#: kallithea/templates/admin/my_account/my_account_watched.html:48 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 msgid "Tip" msgstr "" -#: rhodecode/templates/index_base.html:128 -#: rhodecode/templates/admin/repos/repo_edit.html:114 -#: rhodecode/templates/admin/repos/repos.html:78 +#: kallithea/templates/index_base.html:133 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:53 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:54 +#: kallithea/templates/summary/summary.html:141 msgid "Owner" msgstr "擁有者" -#: rhodecode/templates/index_base.html:136 -#: rhodecode/templates/admin/repos/repos.html:86 -#: rhodecode/templates/admin/users/user_edit_my_account.html:183 -#: rhodecode/templates/admin/users/users.html:107 -#: rhodecode/templates/bookmarks/bookmarks.html:74 -#: rhodecode/templates/branches/branches.html:73 -#: rhodecode/templates/journal/journal.html:204 -#: rhodecode/templates/journal/journal.html:294 -#: rhodecode/templates/tags/tags.html:74 +#: kallithea/templates/index_base.html:141 +#: kallithea/templates/admin/my_account/my_account_repos.html:57 +#: kallithea/templates/admin/my_account/my_account_watched.html:57 +#: kallithea/templates/base/root.html:67 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:208 +#: kallithea/templates/journal/journal.html:299 +#: kallithea/templates/tags/tags.html:81 msgid "Click to sort ascending" msgstr "" -#: rhodecode/templates/index_base.html:137 -#: rhodecode/templates/admin/repos/repos.html:87 -#: rhodecode/templates/admin/users/user_edit_my_account.html:184 -#: rhodecode/templates/admin/users/users.html:108 -#: rhodecode/templates/bookmarks/bookmarks.html:75 -#: rhodecode/templates/branches/branches.html:74 -#: rhodecode/templates/journal/journal.html:205 -#: rhodecode/templates/journal/journal.html:295 -#: rhodecode/templates/tags/tags.html:75 +#: kallithea/templates/index_base.html:142 +#: kallithea/templates/admin/my_account/my_account_repos.html:58 +#: kallithea/templates/admin/my_account/my_account_watched.html:58 +#: kallithea/templates/base/root.html:68 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:209 +#: kallithea/templates/journal/journal.html:300 +#: kallithea/templates/tags/tags.html:82 msgid "Click to sort descending" msgstr "" -#: rhodecode/templates/index_base.html:138 +#: kallithea/templates/index_base.html:143 msgid "No repositories found." msgstr "" -#: rhodecode/templates/index_base.html:139 -#: rhodecode/templates/admin/repos/repos.html:89 -#: rhodecode/templates/admin/users/user_edit_my_account.html:186 -#: rhodecode/templates/admin/users/users.html:110 -#: rhodecode/templates/bookmarks/bookmarks.html:77 -#: rhodecode/templates/branches/branches.html:76 -#: rhodecode/templates/journal/journal.html:207 -#: rhodecode/templates/journal/journal.html:297 -#: rhodecode/templates/tags/tags.html:77 +#: kallithea/templates/index_base.html:144 +#: kallithea/templates/admin/my_account/my_account_repos.html:60 +#: kallithea/templates/admin/my_account/my_account_watched.html:60 +#: kallithea/templates/base/root.html:70 +#: kallithea/templates/bookmarks/bookmarks.html:84 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:211 +#: kallithea/templates/journal/journal.html:302 +#: kallithea/templates/tags/tags.html:84 msgid "Data error." msgstr "" -#: rhodecode/templates/index_base.html:140 -#: rhodecode/templates/admin/repos/repos.html:90 -#: rhodecode/templates/admin/users/user_edit_my_account.html:58 -#: rhodecode/templates/admin/users/user_edit_my_account.html:187 -#: rhodecode/templates/admin/users/users.html:111 -#: rhodecode/templates/bookmarks/bookmarks.html:78 -#: rhodecode/templates/branches/branches.html:77 -#: rhodecode/templates/journal/journal.html:208 -#: rhodecode/templates/journal/journal.html:298 -#: rhodecode/templates/tags/tags.html:78 +#: kallithea/templates/index_base.html:145 +#: kallithea/templates/admin/my_account/my_account_repos.html:61 +#: kallithea/templates/admin/my_account/my_account_watched.html:61 +#: kallithea/templates/base/base.html:151 kallithea/templates/base/root.html:71 +#: kallithea/templates/bookmarks/bookmarks.html:85 +#: kallithea/templates/branches/branches.html:84 +#: kallithea/templates/journal/journal.html:212 +#: kallithea/templates/journal/journal.html:303 +#: kallithea/templates/tags/tags.html:85 msgid "Loading..." msgstr "" -#: rhodecode/templates/login.html:5 rhodecode/templates/base/base.html:239 +#: kallithea/templates/login.html:5 kallithea/templates/login.html:32 +#: kallithea/templates/base/base.html:270 msgid "Log In" msgstr "" -#: rhodecode/templates/login.html:21 +#: kallithea/templates/login.html:30 #, python-format msgid "Log In to %s" msgstr "" -#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20 -#: rhodecode/templates/admin/admin_log.html:5 -#: rhodecode/templates/admin/users/user_add.html:32 -#: rhodecode/templates/admin/users/user_edit.html:57 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:31 -#: rhodecode/templates/admin/users/users.html:77 -#: rhodecode/templates/base/base.html:215 -#: rhodecode/templates/summary/summary.html:123 +#: kallithea/templates/login.html:43 kallithea/templates/register.html:40 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:30 +#: kallithea/templates/admin/users/user_add.html:35 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:53 +#: kallithea/templates/base/base.html:246 msgid "Username" msgstr "帳號" -#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29 -#: rhodecode/templates/admin/ldap/ldap.html:46 -#: rhodecode/templates/admin/users/user_add.html:41 -#: rhodecode/templates/base/base.html:224 +#: kallithea/templates/login.html:52 kallithea/templates/register.html:49 +#: kallithea/templates/admin/my_account/my_account.html:39 +#: kallithea/templates/admin/users/user_add.html:44 +#: kallithea/templates/base/base.html:255 msgid "Password" msgstr "密碼" -#: rhodecode/templates/login.html:50 +#: kallithea/templates/login.html:62 msgid "Remember me" msgstr "" -#: rhodecode/templates/login.html:54 +#: kallithea/templates/login.html:66 msgid "Sign In" msgstr "登入" -#: rhodecode/templates/login.html:60 +#: kallithea/templates/login.html:72 msgid "Forgot your password ?" msgstr "忘記您的密碼?" -#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:235 +#: kallithea/templates/login.html:75 kallithea/templates/base/base.html:266 msgid "Don't have an account ?" msgstr "沒有帳號?" -#: rhodecode/templates/password_reset.html:5 +#: kallithea/templates/password_reset.html:5 msgid "Password Reset" msgstr "" -#: rhodecode/templates/password_reset.html:11 -msgid "Reset your password to" -msgstr "重設您的密碼" - -#: rhodecode/templates/password_reset.html:21 -msgid "Email address" -msgstr "郵件位址" - -#: rhodecode/templates/password_reset.html:30 -msgid "Reset my password" -msgstr "重設我的密碼" - -#: rhodecode/templates/password_reset.html:31 +#: kallithea/templates/password_reset.html:29 +#, python-format +msgid "Reset your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:31 +msgid "Reset your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:42 +msgid "Email Address" +msgstr "" + +#: kallithea/templates/password_reset.html:52 +#: kallithea/templates/register.html:95 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:63 +msgid "Send password reset email" +msgstr "" + +#: kallithea/templates/password_reset.html:64 msgid "Password reset link will be send to matching email address" msgstr "密碼重設連結已郵寄至您的信箱" -#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74 +#: kallithea/templates/register.html:5 kallithea/templates/register.html:30 +#: kallithea/templates/register.html:106 msgid "Sign Up" msgstr "登入" -#: rhodecode/templates/register.html:11 -msgid "Sign Up to" -msgstr "登入" - -#: rhodecode/templates/register.html:38 +#: kallithea/templates/register.html:28 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:58 msgid "Re-enter password" msgstr "確認密碼" -#: rhodecode/templates/register.html:47 -#: rhodecode/templates/admin/users/user_add.html:59 -#: rhodecode/templates/admin/users/user_edit.html:97 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:62 +#: kallithea/templates/register.html:67 +#: kallithea/templates/admin/my_account/my_account_profile.html:41 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:87 msgid "First Name" msgstr "名" -#: rhodecode/templates/register.html:56 -#: rhodecode/templates/admin/users/user_add.html:68 -#: rhodecode/templates/admin/users/user_edit.html:106 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:71 +#: kallithea/templates/register.html:76 +#: kallithea/templates/admin/my_account/my_account_profile.html:50 +#: kallithea/templates/admin/users/user_add.html:71 +#: kallithea/templates/admin/users/user_edit_profile.html:96 msgid "Last Name" msgstr "姓" -#: rhodecode/templates/register.html:65 -#: rhodecode/templates/admin/users/user_add.html:77 -#: rhodecode/templates/admin/users/user_edit.html:115 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:80 -#: rhodecode/templates/summary/summary.html:125 +#: kallithea/templates/register.html:85 +#: kallithea/templates/admin/my_account/my_account_profile.html:59 +#: kallithea/templates/admin/settings/settings.html:44 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:42 msgid "Email" msgstr "電子郵件" -#: rhodecode/templates/register.html:76 +#: kallithea/templates/register.html:108 msgid "Your account will be activated right after registration" msgstr "您的帳號註冊後將會啟用" -#: rhodecode/templates/register.html:78 +#: kallithea/templates/register.html:110 msgid "Your account must wait for activation by administrator" msgstr "您的帳號註冊後將等待管理員啟用" -#: rhodecode/templates/repo_switcher_list.html:10 -#: rhodecode/templates/admin/defaults/defaults.html:44 -#: rhodecode/templates/admin/repos/repo_add_base.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:78 -#: rhodecode/templates/data_table/_dt_elements.html:61 -#: rhodecode/templates/summary/summary.html:77 -msgid "Private repository" -msgstr "私有的版本庫" - -#: rhodecode/templates/repo_switcher_list.html:12 -#: rhodecode/templates/data_table/_dt_elements.html:63 -#: rhodecode/templates/summary/summary.html:79 -msgid "Public repository" -msgstr "公開的版本庫" - -#: rhodecode/templates/switch_to_list.html:10 -#: rhodecode/templates/branches/branches_data.html:57 +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:67 msgid "There are no branches yet" msgstr "沒有任何分支" -#: rhodecode/templates/switch_to_list.html:22 -#: rhodecode/templates/tags/tags_data.html:38 +#: kallithea/templates/switch_to_list.html:16 +msgid "Closed Branches" +msgstr "" + +#: kallithea/templates/switch_to_list.html:32 +#: kallithea/templates/tags/tags_data.html:44 msgid "There are no tags yet" msgstr "沒有任何標籤" -#: rhodecode/templates/switch_to_list.html:35 -#: rhodecode/templates/bookmarks/bookmarks_data.html:37 +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 msgid "There are no bookmarks yet" msgstr "" -#: rhodecode/templates/admin/admin.html:5 -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/base/base.html:73 +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/base/base.html:72 msgid "Admin journal" msgstr "管理員日誌" -#: rhodecode/templates/admin/admin.html:10 +#: kallithea/templates/admin/admin.html:13 msgid "journal filter..." msgstr "" -#: rhodecode/templates/admin/admin.html:12 -#: rhodecode/templates/journal/journal.html:11 +#: kallithea/templates/admin/admin.html:15 +#: kallithea/templates/journal/journal.html:14 msgid "filter" msgstr "" -#: rhodecode/templates/admin/admin.html:13 -#: rhodecode/templates/journal/journal.html:12 +#: kallithea/templates/admin/admin.html:16 +#: kallithea/templates/journal/journal.html:15 #, python-format msgid "%s entry" msgid_plural "%s entries" msgstr[0] "" -#: rhodecode/templates/admin/admin_log.html:6 -#: rhodecode/templates/admin/repos/repos.html:79 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46 -#: rhodecode/templates/admin/users/user_edit_my_account.html:176 -#: rhodecode/templates/admin/users/users.html:87 -#: rhodecode/templates/admin/users_groups/users_groups.html:40 -#: rhodecode/templates/journal/journal.html:197 -#: rhodecode/templates/journal/journal.html:287 +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:50 +#: kallithea/templates/admin/my_account/my_account_watched.html:50 +#: kallithea/templates/admin/repo_groups/repo_groups.html:54 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:55 +#: kallithea/templates/admin/user_groups/user_groups.html:55 +#: kallithea/templates/admin/users/users.html:60 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 msgid "Action" msgstr "動作" -#: rhodecode/templates/admin/admin_log.html:7 -#: rhodecode/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" msgstr "版本庫" -#: rhodecode/templates/admin/admin_log.html:8 -#: rhodecode/templates/bookmarks/bookmarks.html:49 -#: rhodecode/templates/bookmarks/bookmarks_data.html:7 -#: rhodecode/templates/branches/branches.html:48 -#: rhodecode/templates/branches/branches_data.html:7 -#: rhodecode/templates/tags/tags.html:49 -#: rhodecode/templates/tags/tags_data.html:7 +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:52 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:9 msgid "Date" msgstr "時間" -#: rhodecode/templates/admin/admin_log.html:9 +#: kallithea/templates/admin/admin_log.html:9 msgid "From IP" msgstr "來源IP" -#: rhodecode/templates/admin/admin_log.html:63 +#: kallithea/templates/admin/admin_log.html:63 msgid "No actions yet" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:5 -#: rhodecode/templates/admin/defaults/defaults.html:25 +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:14 +#: kallithea/templates/base/base.html:78 +msgid "Authentication" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Authentication Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:34 +msgid "Enabled Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "" +"Comma separated list of plugins. Order of plugins is also order in which " +"Kallithea will try to authenticate user" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:37 +msgid "Available built-in plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:63 +msgid "enabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:43 +#: kallithea/templates/base/root.html:64 +msgid "disabled" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +#: kallithea/templates/admin/defaults/defaults.html:87 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:68 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:72 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:114 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:101 +#: kallithea/templates/admin/repos/repo_edit_settings.html:134 +#: kallithea/templates/admin/settings/settings_hooks.html:53 +#: kallithea/templates/admin/user_groups/user_group_add.html:60 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:67 +#: kallithea/templates/admin/users/user_add.html:99 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "儲存" + +#: kallithea/templates/admin/auth/auth_settings.html:57 +msgid "Plugin" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:28 msgid "Repositories defaults" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:11 -#: rhodecode/templates/base/base.html:80 +#: kallithea/templates/admin/defaults/defaults.html:14 +#: kallithea/templates/base/base.html:79 msgid "Defaults" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:35 -#: rhodecode/templates/admin/repos/repo_add_base.html:38 +#: kallithea/templates/admin/defaults/defaults.html:38 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 msgid "Type" msgstr "類型" -#: rhodecode/templates/admin/defaults/defaults.html:48 -#: rhodecode/templates/admin/repos/repo_add_base.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:82 -#: rhodecode/templates/forks/fork.html:69 +#: kallithea/templates/admin/defaults/defaults.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:77 +#: kallithea/templates/admin/repos/repo_edit_settings.html:82 +#: kallithea/templates/data_table/_dt_elements.html:70 +msgid "Private repository" +msgstr "私有的版本庫" + +#: kallithea/templates/admin/defaults/defaults.html:51 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:75 msgid "" "Private repositories are only visible to people explicitly added as " "collaborators." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:55 -#: rhodecode/templates/admin/repos/repo_edit.html:87 +#: kallithea/templates/admin/defaults/defaults.html:58 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 msgid "Enable statistics" msgstr "啟用統計" -#: rhodecode/templates/admin/defaults/defaults.html:59 -#: rhodecode/templates/admin/repos/repo_edit.html:91 +#: kallithea/templates/admin/defaults/defaults.html:62 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:65 -#: rhodecode/templates/admin/repos/repo_edit.html:96 +#: kallithea/templates/admin/defaults/defaults.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 msgid "Enable downloads" msgstr "啟用下載" -#: rhodecode/templates/admin/defaults/defaults.html:69 -#: rhodecode/templates/admin/repos/repo_edit.html:100 +#: kallithea/templates/admin/defaults/defaults.html:72 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:75 -#: rhodecode/templates/admin/repos/repo_edit.html:105 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:64 +#: kallithea/templates/admin/defaults/defaults.html:78 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 +#: kallithea/templates/admin/repos/repo_edit_settings.html:109 msgid "Enable locking" msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:79 -#: rhodecode/templates/admin/repos/repo_edit.html:109 +#: kallithea/templates/admin/defaults/defaults.html:82 +#: kallithea/templates/admin/repos/repo_edit_settings.html:113 msgid "Enable lock-by-pulling on repository." msgstr "" -#: rhodecode/templates/admin/defaults/defaults.html:84 -#: rhodecode/templates/admin/ldap/ldap.html:89 -#: rhodecode/templates/admin/permissions/permissions.html:122 -#: rhodecode/templates/admin/repos/repo_edit.html:141 -#: rhodecode/templates/admin/repos/repo_edit.html:166 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:72 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:96 -#: rhodecode/templates/admin/settings/hooks.html:73 -#: rhodecode/templates/admin/users/user_add.html:94 -#: rhodecode/templates/admin/users/user_edit.html:140 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:88 -#: rhodecode/templates/admin/users_groups/users_group_add.html:49 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:90 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:143 -#: rhodecode/templates/base/default_perms_box.html:53 -msgid "Save" -msgstr "儲存" - -#: rhodecode/templates/admin/gists/index.html:5 -#: rhodecode/templates/base/base.html:299 -msgid "Gists" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:22 +msgid "Edit Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:40 +#, python-format +msgid "" +"Gist was update since you started editing. Copy your changes and click " +"%(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/new.html:43 +msgid "Gist description ..." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/new.html:45 +msgid "Gist lifetime" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/edit.html:67 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/index.html:62 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/gists/show.html:52 +msgid "Expires" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:65 +#: kallithea/templates/admin/gists/index.html:60 +#: kallithea/templates/admin/gists/show.html:50 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +msgid "never" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:80 +#: kallithea/templates/admin/gists/new.html:52 +#: kallithea/templates/files/files_add.html:59 +#: kallithea/templates/files/files_edit.html:64 +msgid "plain" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:147 +msgid "Update Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:148 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:19 #, python-format msgid "Private Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:12 +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:21 #, python-format msgid "Public Gists for user %s" msgstr "" -#: rhodecode/templates/admin/gists/index.html:14 +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:23 msgid "Public Gists" msgstr "" -#: rhodecode/templates/admin/gists/index.html:31 -#: rhodecode/templates/admin/gists/show.html:24 -#: rhodecode/templates/base/base.html:302 -msgid "Create new gist" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:48 +#: kallithea/templates/admin/gists/index.html:40 +#: kallithea/templates/admin/gists/show.html:28 +msgid "Create New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/data_table/_dt_elements.html:143 msgid "Created" msgstr "" -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/index.html:53 -#: rhodecode/templates/admin/gists/show.html:43 -#: rhodecode/templates/admin/gists/show.html:45 -msgid "Expires" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:51 -#: rhodecode/templates/admin/gists/show.html:43 -msgid "never" -msgstr "" - -#: rhodecode/templates/admin/gists/index.html:68 +#: kallithea/templates/admin/gists/index.html:77 msgid "There are no gists yet" msgstr "" -#: rhodecode/templates/admin/gists/new.html:5 -#: rhodecode/templates/admin/gists/new.html:16 -msgid "New gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:37 -msgid "Gist description ..." -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:52 -msgid "Create private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:53 -msgid "Create public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/new.html:54 -#: rhodecode/templates/admin/permissions/permissions.html:123 -#: rhodecode/templates/admin/permissions/permissions.html:185 -#: rhodecode/templates/admin/repos/repo_edit.html:142 -#: rhodecode/templates/admin/repos/repo_edit.html:167 -#: rhodecode/templates/admin/repos/repo_edit.html:381 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:73 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:97 -#: rhodecode/templates/admin/settings/settings.html:115 -#: rhodecode/templates/admin/settings/settings.html:196 -#: rhodecode/templates/admin/settings/settings.html:288 -#: rhodecode/templates/admin/users/user_edit.html:141 -#: rhodecode/templates/admin/users/user_edit.html:198 -#: rhodecode/templates/admin/users/user_edit.html:246 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:89 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:144 -#: rhodecode/templates/base/default_perms_box.html:54 -#: rhodecode/templates/files/files_add.html:80 -#: rhodecode/templates/files/files_edit.html:66 -#: rhodecode/templates/pullrequests/pullrequest.html:86 +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:22 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:51 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:60 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:61 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:62 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:70 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_password.html:34 +#: kallithea/templates/admin/my_account/my_account_profile.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:109 +#: kallithea/templates/admin/permissions/permissions_ips.html:41 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:115 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:59 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:102 +#: kallithea/templates/admin/repos/repo_edit_settings.html:135 +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:116 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:105 +#: kallithea/templates/admin/users/user_edit_api_keys.html:70 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:50 +#: kallithea/templates/admin/users/user_edit_profile.html:123 +#: kallithea/templates/base/default_perms_box.html:65 +#: kallithea/templates/files/files_add.html:70 +#: kallithea/templates/files/files_delete.html:58 +#: kallithea/templates/files/files_edit.html:73 +#: kallithea/templates/pullrequests/pullrequest.html:83 msgid "Reset" msgstr "重設" -#: rhodecode/templates/admin/gists/show.html:5 -msgid "gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:9 +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:12 msgid "Gist" msgstr "" -#: rhodecode/templates/admin/gists/show.html:36 -msgid "Public gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:38 -msgid "Private gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:54 -#: rhodecode/templates/admin/repos/repo_edit.html:299 -#: rhodecode/templates/changeset/changeset_file_comment.html:40 +#: kallithea/templates/admin/gists/show.html:13 +#: kallithea/templates/email_templates/changeset_comment.html:4 +#: kallithea/templates/email_templates/pull_request.html:4 +#: kallithea/templates/email_templates/pull_request_comment.html:4 +msgid "URL" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:40 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:42 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:59 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:48 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 msgid "Delete" msgstr "移除" -#: rhodecode/templates/admin/gists/show.html:54 -msgid "Confirm to delete this gist" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:63 -#: rhodecode/templates/admin/gists/show.html:84 -#: rhodecode/templates/files/files_edit.html:48 -#: rhodecode/templates/files/files_source.html:25 -#: rhodecode/templates/files/files_source.html:55 -msgid "Show as raw" -msgstr "" - -#: rhodecode/templates/admin/gists/show.html:71 +#: kallithea/templates/admin/gists/show.html:59 +msgid "Confirm to delete this Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:66 +#: kallithea/templates/changeset/changeset_file_comment.html:81 +#: kallithea/templates/changeset/changeset_file_comment.html:190 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +msgid "Edit" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:68 +#: kallithea/templates/files/files_edit.html:54 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:76 msgid "created" msgstr "" -#: rhodecode/templates/admin/ldap/ldap.html:5 -msgid "LDAP administration" -msgstr "LDAP管理者" - -#: rhodecode/templates/admin/ldap/ldap.html:11 -#: rhodecode/templates/admin/users/users.html:86 -#: rhodecode/templates/base/base.html:79 -msgid "LDAP" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:28 -msgid "Connection settings" -msgstr "連接設定" - -#: rhodecode/templates/admin/ldap/ldap.html:30 -msgid "Enable LDAP" -msgstr "啟動LDAP" - -#: rhodecode/templates/admin/ldap/ldap.html:34 -msgid "Host" -msgstr "主機" - -#: rhodecode/templates/admin/ldap/ldap.html:38 -msgid "Port" -msgstr "連接埠" - -#: rhodecode/templates/admin/ldap/ldap.html:42 -msgid "Account" -msgstr "帳號" - -#: rhodecode/templates/admin/ldap/ldap.html:50 -msgid "Connection security" -msgstr "連接安全性" - -#: rhodecode/templates/admin/ldap/ldap.html:54 -msgid "Certificate Checks" -msgstr "憑證確認" - -#: rhodecode/templates/admin/ldap/ldap.html:57 -msgid "Search settings" -msgstr "搜尋選項" - -#: rhodecode/templates/admin/ldap/ldap.html:59 -msgid "Base DN" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:63 -msgid "LDAP Filter" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:67 -msgid "LDAP Search Scope" -msgstr "" - -#: rhodecode/templates/admin/ldap/ldap.html:70 -msgid "Attribute mappings" -msgstr "屬性對應" - -#: rhodecode/templates/admin/ldap/ldap.html:72 -msgid "Login Attribute" -msgstr "登入屬性" - -#: rhodecode/templates/admin/ldap/ldap.html:76 -msgid "First Name Attribute" -msgstr "名" - -#: rhodecode/templates/admin/ldap/ldap.html:80 -msgid "Last Name Attribute" -msgstr "姓" - -#: rhodecode/templates/admin/ldap/ldap.html:84 -msgid "E-mail Attribute" -msgstr "電子郵件屬性" - -#: rhodecode/templates/admin/notifications/notifications.html:5 -#: rhodecode/templates/admin/notifications/notifications.html:9 +#: kallithea/templates/admin/gists/show.html:89 +#: kallithea/templates/files/files_source.html:71 +msgid "Show as raw" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/base/base.html:285 +msgid "My account" +msgstr "我的帳號" + +#: kallithea/templates/admin/my_account/my_account.html:12 +msgid "My Account" +msgstr "我的帳號" + +#: kallithea/templates/admin/my_account/my_account.html:38 +#: kallithea/templates/admin/users/user_edit.html:42 +msgid "Profile" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/admin/users/user_edit.html:43 +msgid "API keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:41 +msgid "My Emails" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:42 +msgid "My Repositories" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:43 +#: kallithea/templates/journal/journal.html:54 +msgid "Watched" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:44 +msgid "Pull requests" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:45 +msgid "My permissions" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:6 +#: kallithea/templates/admin/users/user_edit_api_keys.html:6 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:8 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:27 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:32 +#: kallithea/templates/admin/users/user_edit_api_keys.html:8 +#: kallithea/templates/admin/users/user_edit_api_keys.html:27 +#: kallithea/templates/admin/users/user_edit_api_keys.html:32 +msgid "expires" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#, python-format +msgid "Confirm to reset this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:15 +#: kallithea/templates/admin/users/user_edit_api_keys.html:15 +msgid "reset" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:30 +msgid "expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:40 +#: kallithea/templates/admin/users/user_edit_api_keys.html:40 +#, python-format +msgid "Confirm to remove this api key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:42 +#: kallithea/templates/admin/users/user_edit_api_keys.html:42 +msgid "remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:49 +#: kallithea/templates/admin/users/user_edit_api_keys.html:49 +msgid "No additional api keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +msgid "New api key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:69 +#: kallithea/templates/admin/my_account/my_account_emails.html:45 +#: kallithea/templates/admin/permissions/permissions_ips.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:85 +#: kallithea/templates/admin/repos/repo_edit_fields.html:58 +#: kallithea/templates/admin/users/user_edit_api_keys.html:69 +#: kallithea/templates/admin/users/user_edit_emails.html:45 +#: kallithea/templates/admin/users/user_edit_ips.html:49 +msgid "Add" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:7 +#: kallithea/templates/admin/users/user_edit_emails.html:7 +msgid "Primary" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:19 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:24 +#: kallithea/templates/admin/permissions/permissions_ips.html:14 +#: kallithea/templates/admin/repos/repo_edit_fields.html:18 +#: kallithea/templates/admin/settings/settings_hooks.html:36 +#: kallithea/templates/admin/users/user_edit_emails.html:19 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#: kallithea/templates/data_table/_dt_elements.html:131 +#: kallithea/templates/data_table/_dt_elements.html:159 +#: kallithea/templates/data_table/_dt_elements.html:175 +#: kallithea/templates/data_table/_dt_elements.html:191 +msgid "delete" +msgstr "刪除" + +#: kallithea/templates/admin/my_account/my_account_emails.html:20 +#: kallithea/templates/admin/users/user_edit_emails.html:20 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:26 +#: kallithea/templates/admin/users/user_edit_emails.html:26 +msgid "No additional emails specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:38 +#: kallithea/templates/admin/users/user_edit_emails.html:38 +msgid "New email address" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change your account password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:7 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:69 +msgid "New password" +msgstr "新密碼" + +#: kallithea/templates/admin/my_account/my_account_password.html:25 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:9 +msgid "Change your avatar at" +msgstr "修改您的頭像於" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "使用中" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:13 +msgid "Missing email, please update your user email address." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:26 +msgid "" +"Your user is in an external Source of Record; some details cannot be " +"managed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:2 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:4 +msgid "Show closed pull requests" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:6 +msgid "Opened by me" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:15 +#, python-format +msgid "Pull request #%s opened on %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:17 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:47 +#: kallithea/templates/pullrequests/pullrequest_data.html:11 +#: kallithea/templates/pullrequests/pullrequest_show.html:30 +#: kallithea/templates/pullrequests/pullrequest_show.html:45 +msgid "Closed" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:25 +msgid "Confirm to delete this pull request" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:32 +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:53 +msgid "Nothing here yet" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:36 +msgid "I participate in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_pullrequests.html:44 +#: kallithea/templates/pullrequests/pullrequest_data.html:8 +#, python-format +msgid "Pull request #%s opened by %s on %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories you are owner of" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:59 +#: kallithea/templates/admin/my_account/my_account_watched.html:59 +#: kallithea/templates/base/root.html:69 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:210 +#: kallithea/templates/journal/journal.html:301 +#: kallithea/templates/tags/tags.html:83 +msgid "No records found." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories you are watching" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:5 +#: kallithea/templates/admin/notifications/notifications.html:12 msgid "My Notifications" msgstr "" -#: rhodecode/templates/admin/notifications/notifications.html:29 +#: kallithea/templates/admin/notifications/notifications.html:32 msgid "All" msgstr "" -#: rhodecode/templates/admin/notifications/notifications.html:30 +#: kallithea/templates/admin/notifications/notifications.html:33 msgid "Comments" msgstr "" -#: rhodecode/templates/admin/notifications/notifications.html:31 -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:8 -msgid "Pull requests" -msgstr "" - -#: rhodecode/templates/admin/notifications/notifications.html:35 +#: kallithea/templates/admin/notifications/notifications.html:34 +#: kallithea/templates/base/base.html:196 +msgid "Pull Requests" +msgstr "" + +#: kallithea/templates/admin/notifications/notifications.html:38 msgid "Mark all read" msgstr "" -#: rhodecode/templates/admin/notifications/notifications_data.html:39 +#: kallithea/templates/admin/notifications/notifications_data.html:40 msgid "No notifications here yet" msgstr "" -#: rhodecode/templates/admin/notifications/show_notification.html:5 -#: rhodecode/templates/admin/notifications/show_notification.html:11 +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:14 msgid "Show notification" msgstr "" -#: rhodecode/templates/admin/notifications/show_notification.html:9 -#: rhodecode/templates/base/base.html:253 +#: kallithea/templates/admin/notifications/show_notification.html:12 +#: kallithea/templates/base/base.html:284 msgid "Notifications" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:5 msgid "Permissions administration" msgstr "權限管理員" -#: rhodecode/templates/admin/permissions/permissions.html:11 -#: rhodecode/templates/admin/repos/repo_edit.html:151 -#: rhodecode/templates/admin/repos/repo_edit.html:158 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:81 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:88 -#: rhodecode/templates/admin/users/user_edit.html:150 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:129 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:136 -#: rhodecode/templates/base/base.html:78 +#: kallithea/templates/admin/permissions/permissions.html:14 +#: kallithea/templates/admin/permissions/permissions.html:37 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:55 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:45 +#: kallithea/templates/base/base.html:77 msgid "Permissions" msgstr "權限" -#: rhodecode/templates/admin/permissions/permissions.html:24 -msgid "Default permissions" -msgstr "預設權限" - -#: rhodecode/templates/admin/permissions/permissions.html:31 +#: kallithea/templates/admin/permissions/permissions.html:41 +#: kallithea/templates/admin/settings/settings.html:42 +msgid "Global" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:42 +msgid "IP whitelist" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:43 +msgid "Overview" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 msgid "Anonymous access" msgstr "訪客權限" -#: rhodecode/templates/admin/permissions/permissions.html:49 +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without need to log in. Anonymous users use %s " +"user permissions" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:26 msgid "" "All default permissions on each repository will be reset to chosen " -"permission, note that all custom default permission on repositories will be " -"lost" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:50 -#: rhodecode/templates/admin/permissions/permissions.html:63 -#: rhodecode/templates/admin/permissions/permissions.html:77 +"permission, note that all custom default permission on repositories will " +"be lost" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/admin/permissions/permissions_globals.html:54 msgid "Overwrite existing settings" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:62 +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +#: kallithea/templates/admin/repos/repo_add_base.html:41 +#: kallithea/templates/admin/repos/repo_edit_settings.html:42 +#: kallithea/templates/data_table/_dt_elements.html:204 +#: kallithea/templates/forks/fork.html:51 +msgid "Repository group" +msgstr "版本庫群組" + +#: kallithea/templates/admin/permissions/permissions_globals.html:39 msgid "" "All default permissions on each repository group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:69 +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +#: kallithea/templates/data_table/_dt_elements.html:211 msgid "User group" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:76 +#: kallithea/templates/admin/permissions/permissions_globals.html:53 msgid "" "All default permissions on each user group will be reset to chosen " "permission, note that all custom default permission on repository groups " "will be lost" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:83 +#: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" msgstr "版本庫建立" -#: rhodecode/templates/admin/permissions/permissions.html:91 +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:72 +msgid "" +"Write permission to repository groups allows creating repositories inside" +" that group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:77 msgid "User group creation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:99 +#: kallithea/templates/admin/permissions/permissions_globals.html:85 msgid "Repository forking" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:107 +#: kallithea/templates/admin/permissions/permissions_globals.html:93 msgid "Registration" msgstr "註冊" -#: rhodecode/templates/admin/permissions/permissions.html:115 +#: kallithea/templates/admin/permissions/permissions_globals.html:101 msgid "External auth account activation" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:133 -msgid "Default User Permissions" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:144 -#: rhodecode/templates/admin/users/user_edit.html:207 -msgid "Allowed IP addresses" -msgstr "" - -#: rhodecode/templates/admin/permissions/permissions.html:158 -#: rhodecode/templates/admin/repos/repo_edit.html:340 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 -#: rhodecode/templates/admin/users/user_edit.html:175 -#: rhodecode/templates/admin/users/user_edit.html:220 -#: rhodecode/templates/admin/users_groups/users_groups.html:54 -#: rhodecode/templates/data_table/_dt_elements.html:122 -#: rhodecode/templates/data_table/_dt_elements.html:136 -msgid "delete" -msgstr "刪除" - -#: rhodecode/templates/admin/permissions/permissions.html:159 -#: rhodecode/templates/admin/users/user_edit.html:221 +#: kallithea/templates/admin/permissions/permissions_ips.html:1 +msgid "Default ip whitelist for all users" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:15 +#: kallithea/templates/admin/users/user_edit_ips.html:23 #, python-format msgid "Confirm to delete this ip: %s" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:165 -#: rhodecode/templates/admin/users/user_edit.html:227 +#: kallithea/templates/admin/permissions/permissions_ips.html:21 +#: kallithea/templates/admin/users/user_edit_ips.html:30 msgid "All IP addresses are allowed" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:176 -#: rhodecode/templates/admin/users/user_edit.html:238 +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" msgstr "" -#: rhodecode/templates/admin/permissions/permissions.html:184 -#: rhodecode/templates/admin/repos/repo_add_base.html:73 -#: rhodecode/templates/admin/repos/repo_edit.html:380 -#: rhodecode/templates/admin/users/user_edit.html:197 -#: rhodecode/templates/admin/users/user_edit.html:245 -msgid "Add" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add.html:12 -#: rhodecode/templates/admin/repos/repo_add.html:16 -#: rhodecode/templates/base/base.html:74 rhodecode/templates/base/base.html:88 -#: rhodecode/templates/base/base.html:116 -#: rhodecode/templates/base/base.html:275 -msgid "Repositories" -msgstr "版本庫" - -#: rhodecode/templates/admin/repos/repo_add.html:19 -msgid "Add new" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:20 -#: rhodecode/templates/summary/summary.html:96 -#: rhodecode/templates/summary/summary.html:97 -msgid "Clone from" -msgstr "複製由" - -#: rhodecode/templates/admin/repos/repo_add_base.html:24 -#: rhodecode/templates/admin/repos/repo_edit.html:45 -msgid "Optional http[s] url from which repository should be cloned." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:33 -#: rhodecode/templates/forks/fork.html:51 -msgid "Optionaly select a group to put this repository into." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:42 -msgid "Type of repository to create." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:47 -#: rhodecode/templates/admin/repos/repo_edit.html:59 -#: rhodecode/templates/forks/fork.html:38 -msgid "Landing revision" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:51 -#: rhodecode/templates/admin/repos/repo_edit.html:63 -#: rhodecode/templates/forks/fork.html:42 -msgid "Default revision for files page, downloads, whoosh and readme" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_add_base.html:60 -#: rhodecode/templates/admin/repos/repo_edit.html:72 -#: rhodecode/templates/forks/fork.html:60 -msgid "" -"Keep it short and to the point. Use a README file for longer descriptions." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:8 -msgid "Edit repository" -msgstr "編輯版本庫" - -#: rhodecode/templates/admin/repos/repo_edit.html:12 -#: rhodecode/templates/admin/settings/hooks.html:9 -#: rhodecode/templates/admin/settings/settings.html:11 -#: rhodecode/templates/base/base.html:81 -#: rhodecode/templates/base/base.html:134 -#: rhodecode/templates/summary/summary.html:212 +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default user permissions overview" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:5 +msgid "Add repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:14 +#: kallithea/templates/base/base.html:74 kallithea/templates/base/base.html:93 +msgid "Repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:36 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:35 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "群組名稱" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:54 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "父群組" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:63 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:67 +#: kallithea/templates/admin/repos/repo_add_base.html:54 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository group settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:14 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +msgid "Repository Groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:24 +msgid "Add Child Group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:53 +#: kallithea/templates/admin/repos/repo_edit.html:15 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/settings/settings.html:14 +#: kallithea/templates/admin/settings/settings.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit.html:42 +#: kallithea/templates/base/base.html:80 kallithea/templates/base/base.html:162 msgid "Settings" msgstr "設定" -#: rhodecode/templates/admin/repos/repo_edit.html:36 -msgid "Non-changeable id" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:41 -msgid "Clone uri" -msgstr "複製URL" - -#: rhodecode/templates/admin/repos/repo_edit.html:54 -msgid "Optional select a group to put this repository into." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:119 -msgid "Change owner of this repository." -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:177 -msgid "Advanced settings" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:180 -msgid "Statistics" -msgstr "統計" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Reset current statistics" -msgstr "重設目前的統計" - -#: rhodecode/templates/admin/repos/repo_edit.html:184 -msgid "Confirm to remove current statistics" -msgstr "確認移除目前的統計" - -#: rhodecode/templates/admin/repos/repo_edit.html:187 -msgid "Fetched to rev" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:188 -msgid "Stats gathered" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:196 -msgid "Remote" -msgstr "遠端" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Pull changes from remote location" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:200 -msgid "Confirm to pull changes from remote side" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:211 -msgid "Cache" -msgstr "快取" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Invalidate repository cache" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:215 -msgid "Confirm to invalidate repository cache" -msgstr "確認廢止版本庫快取" - -#: rhodecode/templates/admin/repos/repo_edit.html:218 -msgid "" -"Manually invalidate cache for this repository. On first access repository " -"will be cached again" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:223 -msgid "List of cached values" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:226 -msgid "Prefix" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:227 -msgid "Key" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:228 -#: rhodecode/templates/admin/users/user_add.html:86 -#: rhodecode/templates/admin/users/user_edit.html:124 -#: rhodecode/templates/admin/users/users.html:84 -#: rhodecode/templates/admin/users_groups/users_group_add.html:41 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 -#: rhodecode/templates/admin/users_groups/users_groups.html:39 -msgid "Active" -msgstr "啟用" - -#: rhodecode/templates/admin/repos/repo_edit.html:243 -#: rhodecode/templates/base/base.html:292 -#: rhodecode/templates/base/base.html:293 -msgid "Public journal" -msgstr "公開日誌" - -#: rhodecode/templates/admin/repos/repo_edit.html:249 -msgid "Remove from public journal" -msgstr "從公開日誌移除" - -#: rhodecode/templates/admin/repos/repo_edit.html:251 -msgid "Add to public journal" -msgstr "新增至公開日誌" - -#: rhodecode/templates/admin/repos/repo_edit.html:256 -msgid "" -"All actions made on this repository will be accessible to everyone in public" -" journal" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:263 -msgid "Locking" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Unlock locked repo" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:268 -msgid "Confirm to unlock repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Lock repo" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:271 -msgid "Confirm to lock repository" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:272 -msgid "Repository is not locked" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:277 -msgid "" -"Force locking on repository. Works only when anonymous access is disabled" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:284 -msgid "Set as fork of" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:289 -msgid "Set" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:293 -msgid "Manually set this repository as a fork of another from the list" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Remove this repository" -msgstr "移除版本庫" - -#: rhodecode/templates/admin/repos/repo_edit.html:308 -msgid "Confirm to delete this repository" -msgstr "確認移除這個版本庫" - -#: rhodecode/templates/admin/repos/repo_edit.html:310 -#, python-format -msgid "this repository has %s fork" -msgid_plural "this repository has %s forks" -msgstr[0] "" - -#: rhodecode/templates/admin/repos/repo_edit.html:311 -msgid "Detach forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:312 -msgid "Delete forks" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:315 -msgid "" -"This repository will be renamed in a special way in order to be unaccesible " -"for RhodeCode and VCS systems. If you need to fully delete it from file " -"system please do it manually" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:329 -msgid "Extra fields" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:341 -#, python-format -msgid "Confirm to delete this field: %s" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:355 -msgid "New field key" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:363 -msgid "New field label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:366 -msgid "Enter short label" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:372 -msgid "New field description" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit.html:375 -msgid "Enter description of a field" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:3 -msgid "none" -msgstr "無" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:4 -msgid "read" -msgstr "讀" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:5 -msgid "write" -msgstr "寫" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:6 -msgid "admin" -msgstr "管理員" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:7 -msgid "member" -msgstr "成員" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:16 -msgid "private repository" -msgstr "私有版本庫" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:19 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:28 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:20 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:35 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:20 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:35 -msgid "default" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:33 -#: rhodecode/templates/admin/repos/repo_edit_perms.html:58 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:25 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:55 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:25 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:55 -msgid "revoke" -msgstr "" - -#: rhodecode/templates/admin/repos/repo_edit_perms.html:83 -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81 -#: rhodecode/templates/admin/users_groups/user_group_edit_perms.html:81 -msgid "Add another member" -msgstr "新增另ㄧ位成員" - -#: rhodecode/templates/admin/repos/repos.html:5 -msgid "Repositories administration" -msgstr "版本庫管理員" - -#: rhodecode/templates/admin/repos/repos.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account.html:185 -#: rhodecode/templates/admin/users/users.html:109 -#: rhodecode/templates/bookmarks/bookmarks.html:76 -#: rhodecode/templates/branches/branches.html:75 -#: rhodecode/templates/journal/journal.html:206 -#: rhodecode/templates/journal/journal.html:296 -#: rhodecode/templates/tags/tags.html:76 -msgid "No records found." -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:87 -msgid "apply to children" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:88 -msgid "" -"Set or revoke permission to all children of that group, including non-" -"private repositories and other groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:4 -#, python-format -msgid "%s Group Dashboard" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:9 -msgid "Home" -msgstr "首頁" - -#: rhodecode/templates/admin/repos_groups/repos_groups.html:13 -msgid "with" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5 -msgid "Add repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:11 -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:16 -#: rhodecode/templates/base/base.html:75 rhodecode/templates/base/base.html:91 -msgid "Repository groups" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:13 -msgid "Add new repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:51 -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:56 -msgid "Group parent" -msgstr "父群組" - -#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:59 -msgid "save" -msgstr "儲存" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5 -msgid "Edit repository group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:13 -#, python-format -msgid "Edit repository group %s" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:27 -msgid "Add child group" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:68 -msgid "" -"Enable lock-by-pulling on group. This option will be applied to all other " -"groups and repositories inside" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5 -msgid "Repository groups administration" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:45 -msgid "Number of toplevel repositories" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:64 -#: rhodecode/templates/admin/users_groups/users_groups.html:48 -#: rhodecode/templates/changeset/changeset_file_comment.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:171 -msgid "Edit" -msgstr "" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:65 -#: rhodecode/templates/admin/users_groups/users_groups.html:49 -#: rhodecode/templates/base/perms_summary.html:29 -#: rhodecode/templates/base/perms_summary.html:60 -#: rhodecode/templates/base/perms_summary.html:62 -#: rhodecode/templates/data_table/_dt_elements.html:116 -#: rhodecode/templates/data_table/_dt_elements.html:117 -#: rhodecode/templates/data_table/_dt_elements.html:130 -#: rhodecode/templates/data_table/_dt_elements.html:131 -msgid "edit" -msgstr "編輯" - -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:70 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:54 +#: kallithea/templates/admin/repos/repo_edit.html:49 +#: kallithea/templates/admin/user_groups/user_group_edit.html:43 +#: kallithea/templates/admin/users/user_edit.html:44 +msgid "Advanced" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Created on" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:192 #, python-format msgid "Confirm to delete this group: %s with %s repository" msgid_plural "Confirm to delete this group: %s with %s repositories" msgstr[0] "" -#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:78 -msgid "There are no repository groups yet" -msgstr "" - -#: rhodecode/templates/admin/settings/hooks.html:5 -#: rhodecode/templates/admin/settings/settings.html:5 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "none" +msgstr "無" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "read" +msgstr "讀" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "write" +msgstr "寫" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10 +#: kallithea/templates/base/perms_summary.html:17 +msgid "admin" +msgstr "管理員" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:12 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11 +msgid "user/user group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:24 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:37 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45 +msgid "default" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:43 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:68 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71 +msgid "revoke" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +msgid "delegated admin" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:97 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:94 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:97 +msgid "Add new" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:103 +msgid "apply to children" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:107 +msgid "Both" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:108 +msgid "" +"Set or revoke permission to all children of that group, including non-" +"private repositories and other groups if selected." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "" +"Enable lock-by-pulling on group. This option will be applied to all other" +" groups and repositories inside" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "%s Repository group dashboard" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:12 +msgid "Home" +msgstr "首頁" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:16 +msgid "with" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository groups administration" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:13 +msgid "repository groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:52 +msgid "Number of toplevel repositories" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add.html:5 +msgid "Add repository" +msgstr "新增版本庫" + +#: kallithea/templates/admin/repos/repo_add_base.html:14 +msgid "Import existing repository ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:23 +#: kallithea/templates/summary/summary.html:32 +msgid "Clone from" +msgstr "複製由" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional http[s] url from which repository should be cloned." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:45 +msgid "Keep it short and to the point. Use a README file for longer descriptions." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +#: kallithea/templates/forks/fork.html:55 +msgid "Optionaly select a group to put this repository into." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:63 +msgid "Type of repository to create." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:68 +#: kallithea/templates/admin/repos/repo_edit_settings.html:51 +#: kallithea/templates/forks/fork.html:61 +msgid "Landing revision" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:72 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:16 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:30 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is beeing created, you will be redirected " +"when this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:42 +msgid "" +"We're sorry but error occured during this operation. Please check your " +"Kallithea server logs, or contact administrator." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:8 +#, python-format +msgid "%s repository settings" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Extra fields" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +msgid "Remote" +msgstr "遠端" + +#: kallithea/templates/admin/repos/repo_edit.html:61 +#: kallithea/templates/summary/statistics.html:11 +#: kallithea/templates/summary/summary.html:178 +#: kallithea/templates/summary/summary.html:179 +msgid "Statistics" +msgstr "統計" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +#: kallithea/templates/summary/summary.html:25 +msgid "Fork of" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:6 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:10 +#: kallithea/templates/admin/repos/repo_edit_fork.html:9 +msgid "Manually set this repository as a fork of another from the list" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:24 +msgid "Public journal visibility" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Remove from public journal" +msgstr "從公開日誌移除" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +msgid "Add to public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:43 +msgid "" +"All actions made on this repository will be accessible to everyone in " +"public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:49 +msgid "Change locking" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:56 +msgid "Confirm to unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Unlock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:64 +msgid "Confirm to lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:66 +msgid "Lock repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:68 +msgid "Repository is not locked" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:73 +msgid "" +"Force locking on repository. Works only when anonymous access is " +"disabled. Trigering a pull locks repository by user who pulled, only the " +"same user can unlock by doing a push" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:83 +#: kallithea/templates/data_table/_dt_elements.html:132 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +msgid "Delete this repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:88 +#, python-format +msgid "this repository has %s fork" +msgid_plural "this repository has %s forks" +msgstr[0] "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:89 +msgid "Detach forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:90 +msgid "Delete forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:94 +msgid "" +"This repository will be renamed in a special way in order to be " +"unaccesible for Kallithea and VCS systems. If you need to fully delete it" +" from file system please do it manually" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Invalidate repository cache" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:4 +msgid "Confirm to invalidate repository cache" +msgstr "確認廢止版本庫快取" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:7 +msgid "" +"Manually invalidate cache for this repository. On first access repository" +" will be cached again" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "List of cached values" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:15 +msgid "Prefix" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:16 +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:17 +#: kallithea/templates/admin/user_groups/user_group_add.html:52 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:53 +#: kallithea/templates/admin/users/user_add.html:91 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:57 +msgid "Active" +msgstr "啟用" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:5 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#, python-format +msgid "Confirm to delete this field: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:33 +msgid "New field key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:41 +msgid "New field label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:44 +msgid "Enter short label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:50 +msgid "New field description" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +msgid "Enter description of a field" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:66 +msgid "Extra fields are disabled" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:21 +msgid "private repository" +msgstr "私有版本庫" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:3 +msgid "Remote url" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Pull changes from remote location" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:8 +msgid "Confirm to pull changes from remote side" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:14 +msgid "This repository does not have any remote url set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "Non-changeable id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:11 +msgid "what is that ?" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:13 +msgid "URL by id" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:14 +msgid "" +"In case this repository is renamed or moved into another group the " +"repository url changes.\n" +" Using above url guarantees that this " +"repository will allways be accessible under such url.\n" +" Usefull for CI systems, or any other cases" +" that you need to hardcode the url into 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Clone uri" +msgstr "複製URL" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:27 +#: kallithea/templates/base/perms_summary.html:43 +#: kallithea/templates/base/perms_summary.html:79 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/data_table/_dt_elements.html:124 +#: kallithea/templates/data_table/_dt_elements.html:125 +#: kallithea/templates/data_table/_dt_elements.html:152 +#: kallithea/templates/data_table/_dt_elements.html:153 +#: kallithea/templates/data_table/_dt_elements.html:169 +#: kallithea/templates/data_table/_dt_elements.html:185 +msgid "edit" +msgstr "編輯" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:30 +msgid "new value" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:37 +msgid "http[s] url used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:46 +msgid "Optional select a group to put this repository into." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +#: kallithea/templates/forks/fork.html:65 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +msgid "Change owner of this repository." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:7 +msgid "Processed progress" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Reset statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:10 +msgid "Confirm to remove current statistics" +msgstr "確認移除目前的統計" + +#: kallithea/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "版本庫管理員" + +#: kallithea/templates/admin/repos/repos.html:54 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 msgid "Settings administration" msgstr "設定管理員" -#: rhodecode/templates/admin/settings/hooks.html:24 -msgid "Built in hooks - read only" -msgstr "內建hook - 唯讀" - -#: rhodecode/templates/admin/settings/hooks.html:40 -msgid "Custom hooks" -msgstr "自訂hook" - -#: rhodecode/templates/admin/settings/hooks.html:56 -msgid "remove" -msgstr "移除" - -#: rhodecode/templates/admin/settings/hooks.html:88 -msgid "Failed to remove hook" -msgstr "移除hook失敗" - -#: rhodecode/templates/admin/settings/settings.html:26 -msgid "Remap and rescan repositories" -msgstr "重新對映與掃描版本庫" - -#: rhodecode/templates/admin/settings/settings.html:34 -msgid "Rescan option" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:40 -msgid "" -"In case a repository was deleted from filesystem and there are leftovers in " -"the database check this option to scan obsolete data in database and remove " -"it." -msgstr "如果版本庫已從檔案系統中刪除,但是資料還留在資料庫,請勾選這個項目清理資料庫中舊的資料" - -#: rhodecode/templates/admin/settings/settings.html:41 -msgid "Destroy old data" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:43 +#: kallithea/templates/admin/settings/settings.html:40 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:41 +msgid "Remap and rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:43 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:45 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:46 +msgid "Full text search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:47 +msgid "System Info" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:4 +msgid "Email prefix" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:5 +msgid "Kallithea email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:6 +msgid "Error email from" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:7 +msgid "Error email recipients" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:9 +msgid "SMTP server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:10 +msgid "SMTP username" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:11 +msgid "SMTP password" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "SMTP port" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:14 +msgid "SMTP use TLS" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:15 +msgid "SMTP use SSL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:16 +msgid "SMTP auth" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:31 +msgid "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:39 +msgid "Send" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:8 +msgid "Site branding" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:18 +msgid "HTTP authentication realm" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:27 +msgid "Google Analytics code" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:36 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:46 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:50 msgid "" -"Rescan repositories location for new repositories. Also deletes obsolete if " -"`destroy` flag is checked " -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:48 -msgid "Rescan repositories" -msgstr "重新掃描版本庫" - -#: rhodecode/templates/admin/settings/settings.html:54 -msgid "Whoosh indexing" -msgstr "Whoosh 索引" - -#: rhodecode/templates/admin/settings/settings.html:62 -msgid "Index build option" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:67 -msgid "Build from scratch" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:73 -msgid "Reindex" -msgstr "重新索引" - -#: rhodecode/templates/admin/settings/settings.html:79 -msgid "Global application settings" -msgstr "全域設定" - -#: rhodecode/templates/admin/settings/settings.html:88 -msgid "Site branding" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:97 -msgid "HTTP authentication realm" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:106 -msgid "Google Analytics code" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:114 -#: rhodecode/templates/admin/settings/settings.html:195 -#: rhodecode/templates/admin/settings/settings.html:287 +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:55 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:115 msgid "Save settings" msgstr "儲存設定" -#: rhodecode/templates/admin/settings/settings.html:121 -msgid "Visualisation settings" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:129 -msgid "General" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:134 -msgid "Use repository extra fields" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:136 -msgid "Allows storing additional customized fields per repository." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:139 -msgid "Show RhodeCode version" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:141 -msgid "Shows or hides displayed version of RhodeCode in the footer" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:146 -msgid "Dashboard items" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:150 +#: kallithea/templates/admin/settings/settings_hooks.html:1 +msgid "Built in Mercurial hooks - read only" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:15 +msgid "" +"Hooks can be used to trigger actions on certain events such as push / " +"pull. They can trigger Python functions or external applications." +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:19 +msgid "Custom hooks" +msgstr "自訂hook" + +#: kallithea/templates/admin/settings/settings_hooks.html:69 +msgid "Failed to remove hook" +msgstr "移除hook失敗" + +#: kallithea/templates/admin/settings/settings_mapping.html:6 +msgid "Rescan option" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:11 +msgid "Destroy old data" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:13 +msgid "" +"In case a repository was deleted from filesystem and it still exists in " +"the database check this option to scan obsolete data in database and " +"remove it." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:17 +msgid "Invalidate cache for all repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:19 +msgid "" +"Each cache data for repositories will be cleaned with this option " +"selected. Use this to reload data and clear cache keys." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:23 +msgid "Install GIT hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 +msgid "" +"Verify if Kallitheas GIT hooks are installed for each repository. Current" +" hooks will be updated to latest version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:32 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:7 +msgid "Index build option" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:12 +msgid "Build from scratch" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:15 msgid "" -"Number of items displayed in lightweight dashboard before pagination is " -"shown." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:155 -msgid "Icons" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:160 -msgid "Show public repo icon on repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:164 -msgid "Show private repo icon on repositories" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:166 -msgid "Show public/private icons next to repositories names" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:172 -msgid "Meta-Tagging" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:177 -msgid "Stylify recognised metatags:" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:204 -msgid "VCS settings" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:213 +"This option completely reindex all the files within Kallithea for proper " +"fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:21 +msgid "Reindex" +msgstr "重新索引" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:4 +msgid "check for updates" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:5 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:6 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "GIT version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "GIT path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Upgrade info endpoint" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Note: please make sure this server can access this url" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:14 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:6 msgid "Web" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:218 +#: kallithea/templates/admin/settings/settings_vcs.html:11 msgid "Require SSL for vcs operations" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:220 +#: kallithea/templates/admin/settings/settings_vcs.html:13 msgid "" -"RhodeCode will require SSL for pushing or pulling. If SSL is missing it will" -" return HTTP Error 406: Not Acceptable" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:226 -msgid "Hooks" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:231 +"Activate to set Kallithea to require SSL for pushing or pulling. If SSL " +"certificate is missing it will return a HTTP Error 406: Not Acceptable." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:24 +msgid "Show repository size after push" +msgstr "push 後顯示版本庫大小" + +#: kallithea/templates/admin/settings/settings_vcs.html:28 +msgid "Log user push commands" +msgstr "紀錄使用者推送命令" + +#: kallithea/templates/admin/settings/settings_vcs.html:32 +msgid "Log user pull commands" +msgstr "紀錄使用者抓取命令" + +#: kallithea/templates/admin/settings/settings_vcs.html:36 msgid "Update repository after push (hg update)" msgstr "push後更新版本庫 (hg update)" -#: rhodecode/templates/admin/settings/settings.html:235 -msgid "Show repository size after push" -msgstr "push 後顯示版本庫大小" - -#: rhodecode/templates/admin/settings/settings.html:239 -msgid "Log user push commands" -msgstr "紀錄使用者推送命令" - -#: rhodecode/templates/admin/settings/settings.html:243 -msgid "Log user pull commands" -msgstr "紀錄使用者抓取命令" - -#: rhodecode/templates/admin/settings/settings.html:247 -msgid "Advanced setup" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:252 +#: kallithea/templates/admin/settings/settings_vcs.html:42 msgid "Mercurial Extensions" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:257 +#: kallithea/templates/admin/settings/settings_vcs.html:47 msgid "Enable largefiles extension" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:261 +#: kallithea/templates/admin/settings/settings_vcs.html:51 msgid "Enable hgsubversion extension" msgstr "" -#: rhodecode/templates/admin/settings/settings.html:263 +#: kallithea/templates/admin/settings/settings_vcs.html:53 msgid "" -"Requires hgsubversion library installed. Allows cloning from svn remote " -"locations" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:274 +"Requires hgsubversion library to be installed. Allows cloning remote SVN " +"repositories and migrates them to Mercurial type." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 msgid "Repositories location" msgstr "版本庫路徑" -#: rhodecode/templates/admin/settings/settings.html:279 +#: kallithea/templates/admin/settings/settings_vcs.html:69 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting" +" take effect." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:72 +msgid "" +"Filesystem location where repositories should be stored. After changing " +"this value a restart and rescan of the repository folder are required." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:8 +msgid "General" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:13 +msgid "Use repository extra fields" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:15 +msgid "Allows storing additional customized fields per repository." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:18 +msgid "Show Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:24 +msgid "Use Gravatars in Kallithea" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:30 msgid "" -"Click to unlock. You must restart RhodeCode in order to make this setting " -"take effect." -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:280 -#: rhodecode/templates/base/base.html:143 -msgid "Unlock" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:282 +"Gravatar url allows you to use other avatar server application.\n" +" Following " +"variables of the URL will be replaced accordingly.\n" +" {scheme} " +"'http' or 'https' sent from running Kallithea server,\n" +" {email} user " +"email,\n" +" {md5email} md5 " +"hash of the user email (like at gravatar.com),\n" +" {size} size " +"of the image that is expected from the server application,\n" +" {netloc} " +"network location/server host of running Kallithea server" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:42 +msgid "" +"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}'," +" available vars:\n" +" {scheme} 'http' " +"or 'https' sent from running Kallithea server,\n" +" {user} current " +"user username,\n" +" {netloc} network " +"location/server host of running Kallithea server,\n" +" {repo} full " +"repository name,\n" +" {repoid} ID of " +"repository, can be used to contruct clone-by-id" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:54 +msgid "Dashboard items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:58 +msgid "" +"Number of items displayed in the main page dashboard before pagination is" +" shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:64 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:68 msgid "" -"Location where repositories are stored. After changing this value a restart," -" and rescan is required" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:303 -msgid "Test Email" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:311 -msgid "Email to" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:319 -msgid "Send" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:325 -msgid "System Info and Packages" -msgstr "" - -#: rhodecode/templates/admin/settings/settings.html:328 -#: rhodecode/templates/changelog/changelog.html:51 -msgid "Show" -msgstr "顯示" - -#: rhodecode/templates/admin/users/user_add.html:5 +"Number of items displayed in the admin pages grids before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:74 +msgid "Icons" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:79 +msgid "Show public repo icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:83 +msgid "Show private repo icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:85 +msgid "Show public/private icons next to repositories names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:91 +msgid "Meta-Tagging" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:96 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:110 +msgid "" +"Parses meta tags from repository description field and turns them into " +"colored tags." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:5 +msgid "Add user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:13 +#: kallithea/templates/base/base.html:76 kallithea/templates/base/base.html:96 +msgid "User groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:28 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:47 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:19 +msgid "Short, optional description for this user group." +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:5 +#, python-format +msgid "%s user group settings" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:14 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:44 +#: kallithea/templates/admin/users/user_edit.html:45 +msgid "Default permissions" +msgstr "預設權限" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:32 +#: kallithea/templates/admin/user_groups/user_groups.html:52 +msgid "Members" +msgstr "成員" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1 +#, python-format +msgid "User Group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:176 +#, python-format +msgid "Confirm to delete this user group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:15 +msgid "No members yet" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:40 +msgid "Chosen group members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:43 +msgid "Remove all elements" +msgstr "移除所有元素" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:53 +msgid "Available members" +msgstr "啟用的成員" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:56 +msgid "Add all elements" +msgstr "新增索有元素" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User groups administration" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:13 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 msgid "Add user" msgstr "新增使用者" -#: rhodecode/templates/admin/users/user_add.html:10 -#: rhodecode/templates/admin/users/user_edit.html:11 -#: rhodecode/templates/base/base.html:76 +#: kallithea/templates/admin/users/user_add.html:13 +#: kallithea/templates/admin/users/user_edit.html:14 +#: kallithea/templates/base/base.html:75 msgid "Users" msgstr "使用者" -#: rhodecode/templates/admin/users/user_add.html:12 -#: rhodecode/templates/admin/users/users.html:23 -msgid "Add new user" -msgstr "" - -#: rhodecode/templates/admin/users/user_add.html:50 +#: kallithea/templates/admin/users/user_add.html:15 +#: kallithea/templates/admin/users/users.html:27 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:53 msgid "Password confirmation" msgstr "" -#: rhodecode/templates/admin/users/user_edit.html:5 -msgid "Edit user" -msgstr "編輯使用者" - -#: rhodecode/templates/admin/users/user_edit.html:13 -#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 -#, python-format -msgid "Edit %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:34 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:10 -msgid "Change your avatar at" -msgstr "修改您的頭像於" - -#: rhodecode/templates/admin/users/user_edit.html:35 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:11 -msgid "Using" -msgstr "使用中" - -#: rhodecode/templates/admin/users/user_edit.html:43 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:20 -msgid "API key" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:50 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:25 -msgid "Current IP" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:70 -msgid "LDAP DN" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:79 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:44 -msgid "New password" -msgstr "新密碼" - -#: rhodecode/templates/admin/users/user_edit.html:88 -#: rhodecode/templates/admin/users/user_edit_my_account_form.html:53 +#: kallithea/templates/admin/users/user_edit.html:5 +#, python-format +msgid "%s user settings" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:46 +msgid "Emails" +msgstr "" + +#: kallithea/templates/admin/users/user_edit.html:47 +msgid "Ip whitelist" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:1 +#, python-format +msgid "User: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_profile.html:51 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +msgid "Last Login" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:10 +msgid "Member of User groups" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:160 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:8 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:8 +msgid "Change avatar at" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Missing email, please update this user email address." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:27 +#, python-format +msgid "" +"This user is in an external Source of Record (%s); some details cannot be" +" managed here." +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:60 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:78 msgid "New password confirmation" msgstr "" -#: rhodecode/templates/admin/users/user_edit.html:163 -msgid "Email addresses" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:176 -#, python-format -msgid "Confirm to delete this email: %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit.html:190 -msgid "New email address" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:5 -#: rhodecode/templates/base/base.html:254 -msgid "My account" -msgstr "我的帳號" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:9 -msgid "My Account" -msgstr "我的帳號" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:35 -msgid "My permissions" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:38 -#: rhodecode/templates/journal/journal.html:54 -msgid "My repos" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account.html:41 -msgid "My pull requests" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:4 -msgid "Show closed pull requests" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:6 -msgid "Opened by me" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15 -#, python-format -msgid "Pull request #%s opened on %s" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:17 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:45 -#: rhodecode/templates/pullrequests/pullrequest_data.html:11 -#: rhodecode/templates/pullrequests/pullrequest_show.html:27 -#: rhodecode/templates/pullrequests/pullrequest_show.html:42 -msgid "Closed" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:23 -msgid "Confirm to delete this pull request" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:30 -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:51 -msgid "Nothing here yet" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:34 -msgid "I participate in" -msgstr "" - -#: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:42 -#: rhodecode/templates/pullrequests/pullrequest_data.html:8 -#, python-format -msgid "Pull request #%s opened by %s on %s" -msgstr "" - -#: rhodecode/templates/admin/users/users.html:5 +#: kallithea/templates/admin/users/users.html:5 msgid "Users administration" msgstr "使用者管理員" -#: rhodecode/templates/admin/users/users.html:9 +#: kallithea/templates/admin/users/users.html:13 msgid "users" msgstr "使用者" -#: rhodecode/templates/admin/users/users.html:80 +#: kallithea/templates/admin/users/users.html:54 msgid "Firstname" msgstr "" -#: rhodecode/templates/admin/users/users.html:81 +#: kallithea/templates/admin/users/users.html:55 msgid "Lastname" msgstr "" -#: rhodecode/templates/admin/users/users.html:82 +#: kallithea/templates/admin/users/users.html:56 msgid "Last login" msgstr "" -#: rhodecode/templates/admin/users_groups/users_group_add.html:5 -msgid "Add user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:10 -#: rhodecode/templates/admin/users_groups/users_groups.html:11 -#: rhodecode/templates/base/base.html:77 rhodecode/templates/base/base.html:94 -msgid "User groups" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_add.html:12 -#: rhodecode/templates/admin/users_groups/users_groups.html:26 -msgid "Add new user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 -msgid "Edit user group" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 -msgid "UserGroups" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 -#: rhodecode/templates/admin/users_groups/users_groups.html:38 -msgid "Members" -msgstr "成員" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 -msgid "Chosen group members" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 -msgid "Remove all elements" -msgstr "移除所有元素" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 -msgid "Available members" -msgstr "啟用的成員" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 -msgid "Add all elements" -msgstr "新增索有元素" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:109 -msgid "No members yet" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_group_edit.html:117 -msgid "Global Permissions" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:5 -msgid "User groups administration" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:55 -#, python-format -msgid "Confirm to delete this user group: %s" -msgstr "" - -#: rhodecode/templates/admin/users_groups/users_groups.html:62 -msgid "There are no user groups yet" -msgstr "" - -#: rhodecode/templates/base/base.html:42 +#: kallithea/templates/admin/users/users.html:59 +msgid "Auth type" +msgstr "" + +#: kallithea/templates/base/base.html:37 #, python-format msgid "Server instance: %s" msgstr "" -#: rhodecode/templates/base/base.html:52 -msgid "Report a bug" -msgstr "" - -#: rhodecode/templates/base/base.html:121 -#: rhodecode/templates/data_table/_dt_elements.html:9 -#: rhodecode/templates/data_table/_dt_elements.html:11 -#: rhodecode/templates/data_table/_dt_elements.html:13 -#: rhodecode/templates/summary/summary.html:8 +#: kallithea/templates/base/base.html:49 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:134 +msgid "Create fork" +msgstr "" + +#: kallithea/templates/base/base.html:145 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:11 msgid "Summary" msgstr "概況" -#: rhodecode/templates/base/base.html:122 -#: rhodecode/templates/changelog/changelog.html:15 -#: rhodecode/templates/data_table/_dt_elements.html:17 -#: rhodecode/templates/data_table/_dt_elements.html:19 -#: rhodecode/templates/data_table/_dt_elements.html:21 +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/changelog/changelog.html:17 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 msgid "Changelog" msgstr "修改紀錄" -#: rhodecode/templates/base/base.html:123 -#: rhodecode/templates/data_table/_dt_elements.html:25 -#: rhodecode/templates/data_table/_dt_elements.html:27 -#: rhodecode/templates/data_table/_dt_elements.html:29 -#: rhodecode/templates/files/files.html:12 +#: kallithea/templates/base/base.html:147 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:15 msgid "Files" msgstr "檔案" -#: rhodecode/templates/base/base.html:125 +#: kallithea/templates/base/base.html:149 msgid "Switch To" msgstr "" -#: rhodecode/templates/base/base.html:127 -#: rhodecode/templates/base/base.html:279 -msgid "loading..." -msgstr "載入中..." - -#: rhodecode/templates/base/base.html:131 +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/base/base.html:158 msgid "Options" msgstr "選項" -#: rhodecode/templates/base/base.html:137 -#: rhodecode/templates/forks/forks_data.html:21 +#: kallithea/templates/base/base.html:166 +#: kallithea/templates/forks/forks_data.html:21 msgid "Compare fork" msgstr "" -#: rhodecode/templates/base/base.html:139 -#: rhodecode/templates/base/base.html:312 -#: rhodecode/templates/search/search.html:14 -#: rhodecode/templates/search/search.html:54 +#: kallithea/templates/base/base.html:168 +#: kallithea/templates/bookmarks/bookmarks.html:58 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:57 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:58 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "" + +#: kallithea/templates/base/base.html:170 +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/search/search.html:17 +#: kallithea/templates/search/search.html:57 msgid "Search" msgstr "搜尋" -#: rhodecode/templates/base/base.html:145 +#: kallithea/templates/base/base.html:174 +msgid "Unlock" +msgstr "" + +#: kallithea/templates/base/base.html:176 msgid "Lock" msgstr "" -#: rhodecode/templates/base/base.html:153 +#: kallithea/templates/base/base.html:184 msgid "Follow" msgstr "" -#: rhodecode/templates/base/base.html:154 +#: kallithea/templates/base/base.html:185 msgid "Unfollow" msgstr "" -#: rhodecode/templates/base/base.html:157 -#: rhodecode/templates/data_table/_dt_elements.html:33 -#: rhodecode/templates/data_table/_dt_elements.html:35 -#: rhodecode/templates/data_table/_dt_elements.html:37 -#: rhodecode/templates/data_table/_dt_elements.html:74 -#: rhodecode/templates/forks/fork.html:9 +#: kallithea/templates/base/base.html:188 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:12 msgid "Fork" msgstr "分支" -#: rhodecode/templates/base/base.html:159 +#: kallithea/templates/base/base.html:190 msgid "Create Pull Request" msgstr "" -#: rhodecode/templates/base/base.html:165 -msgid "Show Pull Requests" -msgstr "" - -#: rhodecode/templates/base/base.html:165 -msgid "Pull Requests" -msgstr "" - -#: rhodecode/templates/base/base.html:202 +#: kallithea/templates/base/base.html:196 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "" + +#: kallithea/templates/base/base.html:233 msgid "Not logged in" msgstr "" -#: rhodecode/templates/base/base.html:209 +#: kallithea/templates/base/base.html:240 msgid "Login to your account" msgstr "" -#: rhodecode/templates/base/base.html:232 +#: kallithea/templates/base/base.html:263 msgid "Forgot password ?" msgstr "忘記密碼?" -#: rhodecode/templates/base/base.html:255 +#: kallithea/templates/base/base.html:286 msgid "Log Out" msgstr "登出" -#: rhodecode/templates/base/base.html:274 -msgid "Switch repository" -msgstr "切換版本庫" - -#: rhodecode/templates/base/base.html:286 +#: kallithea/templates/base/base.html:311 msgid "Show recent activity" msgstr "" -#: rhodecode/templates/base/base.html:287 -#: rhodecode/templates/journal/journal.html:4 +#: kallithea/templates/base/base.html:312 +#: kallithea/templates/journal/journal.html:4 msgid "Journal" msgstr "日誌" -#: rhodecode/templates/base/base.html:298 +#: kallithea/templates/base/base.html:317 +#: kallithea/templates/base/base.html:318 +msgid "Public journal" +msgstr "公開日誌" + +#: kallithea/templates/base/base.html:323 msgid "Show public gists" msgstr "" -#: rhodecode/templates/base/base.html:303 +#: kallithea/templates/base/base.html:324 +msgid "Gists" +msgstr "" + +#: kallithea/templates/base/base.html:327 +msgid "Create new gist" +msgstr "" + +#: kallithea/templates/base/base.html:328 msgid "All public gists" msgstr "" -#: rhodecode/templates/base/base.html:305 +#: kallithea/templates/base/base.html:330 msgid "My public gists" msgstr "" -#: rhodecode/templates/base/base.html:306 +#: kallithea/templates/base/base.html:331 msgid "My private gists" msgstr "" -#: rhodecode/templates/base/base.html:311 +#: kallithea/templates/base/base.html:336 msgid "Search in repositories" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:14 -msgid "Inherit default permissions" -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:18 +#: kallithea/templates/base/base.html:399 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:527 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:536 +msgid "Site-wide shortcuts" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:14 +msgid "Inherit from defaults" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:19 #, python-format msgid "" -"Select to inherit permissions from %s settings. With this selected below " -"options does not apply." -msgstr "" - -#: rhodecode/templates/base/default_perms_box.html:26 +"Select to inherit permissions from %s permissions settings, and default " +"IP address whitelist." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:28 msgid "Create repositories" msgstr "建立版本庫" -#: rhodecode/templates/base/default_perms_box.html:30 +#: kallithea/templates/base/default_perms_box.html:33 msgid "Select this option to allow repository creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:35 +#: kallithea/templates/base/default_perms_box.html:40 msgid "Create user groups" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:39 +#: kallithea/templates/base/default_perms_box.html:45 msgid "Select this option to allow user group creation for this user" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:44 +#: kallithea/templates/base/default_perms_box.html:52 msgid "Fork repositories" msgstr "" -#: rhodecode/templates/base/default_perms_box.html:48 +#: kallithea/templates/base/default_perms_box.html:57 msgid "Select this option to allow repository forking for this user" msgstr "" -#: rhodecode/templates/base/perms_summary.html:11 +#: kallithea/templates/base/perms_summary.html:13 +msgid "show" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:22 msgid "No permissions defined yet" msgstr "" -#: rhodecode/templates/base/perms_summary.html:19 -#: rhodecode/templates/base/perms_summary.html:38 +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 msgid "Permission" msgstr "" -#: rhodecode/templates/base/perms_summary.html:20 -#: rhodecode/templates/base/perms_summary.html:39 +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:56 msgid "Edit Permission" msgstr "" -#: rhodecode/templates/base/root.html:44 +#: kallithea/templates/base/perms_summary.html:90 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:45 msgid "Add another comment" msgstr "" -#: rhodecode/templates/base/root.html:45 -#: rhodecode/templates/data_table/_dt_elements.html:147 +#: kallithea/templates/base/root.html:46 +#: kallithea/templates/data_table/_dt_elements.html:216 msgid "Stop following this repository" msgstr "停止追蹤這個版本庫" -#: rhodecode/templates/base/root.html:46 +#: kallithea/templates/base/root.html:47 msgid "Start following this repository" msgstr "開始追蹤這個版本庫" -#: rhodecode/templates/base/root.html:47 +#: kallithea/templates/base/root.html:48 msgid "Group" msgstr "群組" -#: rhodecode/templates/base/root.html:48 +#: kallithea/templates/base/root.html:49 msgid "members" msgstr "成員" -#: rhodecode/templates/base/root.html:49 -#: rhodecode/templates/pullrequests/pullrequest.html:203 +#: kallithea/templates/base/root.html:50 +#: kallithea/templates/pullrequests/pullrequest.html:202 msgid "Loading ..." msgstr "" -#: rhodecode/templates/base/root.html:50 +#: kallithea/templates/base/root.html:51 +msgid "loading ..." +msgstr "" + +#: kallithea/templates/base/root.html:52 msgid "Search truncated" msgstr "" -#: rhodecode/templates/base/root.html:51 +#: kallithea/templates/base/root.html:53 msgid "No matching files" msgstr "" -#: rhodecode/templates/base/root.html:52 -#: rhodecode/templates/changelog/changelog.html:45 +#: kallithea/templates/base/root.html:54 +#: kallithea/templates/changelog/changelog.html:51 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:33 msgid "Open new pull request" msgstr "" -#: rhodecode/templates/base/root.html:53 +#: kallithea/templates/base/root.html:55 msgid "Open new pull request for selected changesets" msgstr "" -#: rhodecode/templates/base/root.html:54 +#: kallithea/templates/base/root.html:56 msgid "Show selected changesets __S -> __E" msgstr "" -#: rhodecode/templates/base/root.html:55 +#: kallithea/templates/base/root.html:57 msgid "Show selected changeset __S" msgstr "" -#: rhodecode/templates/base/root.html:56 +#: kallithea/templates/base/root.html:58 msgid "Selection link" msgstr "" -#: rhodecode/templates/base/root.html:57 -#: rhodecode/templates/changeset/diff_block.html:8 +#: kallithea/templates/base/root.html:59 +#: kallithea/templates/changeset/diff_block.html:8 msgid "Collapse diff" msgstr "" -#: rhodecode/templates/base/root.html:58 +#: kallithea/templates/base/root.html:60 msgid "Expand diff" msgstr "" -#: rhodecode/templates/base/root.html:59 +#: kallithea/templates/base/root.html:61 msgid "Failed to revoke permission" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:5 +#: kallithea/templates/base/root.html:62 +msgid "confirm to revoke permission for {0}: {1} ?" +msgstr "" + +#: kallithea/templates/base/root.html:66 +msgid "specify changeset" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:5 #, python-format msgid "%s Bookmarks" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:26 -msgid "Compare bookmarks" -msgstr "" - -#: rhodecode/templates/bookmarks/bookmarks.html:51 -#: rhodecode/templates/bookmarks/bookmarks_data.html:8 -#: rhodecode/templates/branches/branches.html:50 -#: rhodecode/templates/branches/branches_data.html:8 -#: rhodecode/templates/changelog/changelog_summary_data.html:8 -#: rhodecode/templates/tags/tags.html:51 -#: rhodecode/templates/tags/tags_data.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:29 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:55 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/tags/tags.html:55 +#: kallithea/templates/tags/tags_data.html:10 msgid "Author" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.html:52 -#: rhodecode/templates/bookmarks/bookmarks_data.html:9 -#: rhodecode/templates/branches/branches.html:51 -#: rhodecode/templates/branches/branches_data.html:9 -#: rhodecode/templates/changelog/changelog_summary_data.html:5 -#: rhodecode/templates/tags/tags.html:52 -#: rhodecode/templates/tags/tags_data.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:55 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:5 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:12 msgid "Revision" msgstr "修訂" -#: rhodecode/templates/bookmarks/bookmarks.html:54 -#: rhodecode/templates/bookmarks/bookmarks_data.html:10 -#: rhodecode/templates/branches/branches.html:53 -#: rhodecode/templates/branches/branches_data.html:10 -#: rhodecode/templates/tags/tags.html:54 -#: rhodecode/templates/tags/tags_data.html:10 -msgid "Compare" -msgstr "" - -#: rhodecode/templates/branches/branches.html:5 +#: kallithea/templates/branches/branches.html:5 #, python-format msgid "%s Branches" msgstr "" -#: rhodecode/templates/branches/branches.html:26 -msgid "Compare branches" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:6 +#: kallithea/templates/branches/branches.html:29 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 #, python-format msgid "%s Changelog" msgstr "" -#: rhodecode/templates/changelog/changelog.html:19 +#: kallithea/templates/changelog/changelog.html:21 #, python-format msgid "showing %d out of %d revision" msgid_plural "showing %d out of %d revisions" msgstr[0] "" -#: rhodecode/templates/changelog/changelog.html:39 +#: kallithea/templates/changelog/changelog.html:43 msgid "Clear selection" msgstr "" -#: rhodecode/templates/changelog/changelog.html:42 -#: rhodecode/templates/forks/forks_data.html:19 +#: kallithea/templates/changelog/changelog.html:47 +#: kallithea/templates/forks/forks_data.html:19 #, python-format msgid "Compare fork with %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:42 -msgid "Compare fork with parent" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:78 -#: rhodecode/templates/changelog/changelog_summary_data.html:28 -#, python-format -msgid "Click to open associated pull request #%s" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:102 -#: rhodecode/templates/summary/summary.html:403 -msgid "Show more" -msgstr "" - -#: rhodecode/templates/changelog/changelog.html:115 -#: rhodecode/templates/changelog/changelog_summary_data.html:50 -#: rhodecode/templates/changeset/changeset.html:107 -#: rhodecode/templates/changeset/changeset_range.html:86 +#: kallithea/templates/changelog/changelog.html:49 +#, python-format +msgid "Compare fork with Parent(%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:56 +msgid "Show" +msgstr "顯示" + +#: kallithea/templates/changelog/changelog.html:82 +#: kallithea/templates/changelog/changelog_summary_data.html:19 +#, python-format +msgid "" +"Changeset status: %s\n" +"Click to open associated pull request #%s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:86 +#: kallithea/templates/compare/compare_cs.html:18 +#, python-format +msgid "Changeset status: %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:105 +#: kallithea/templates/compare/compare_cs.html:36 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:114 +msgid "Changeset has comments" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/changelog/changelog_summary_data.html:50 +#: kallithea/templates/changeset/changeset.html:93 +#: kallithea/templates/changeset/changeset_range.html:93 #, python-format msgid "Bookmark %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:121 -#: rhodecode/templates/changelog/changelog_summary_data.html:56 -#: rhodecode/templates/changeset/changeset.html:113 -#: rhodecode/templates/changeset/changeset_range.html:92 +#: kallithea/templates/changelog/changelog.html:130 +#: kallithea/templates/changelog/changelog_summary_data.html:56 +#: kallithea/templates/changeset/changeset.html:100 +#: kallithea/templates/changeset/changeset_range.html:99 #, python-format msgid "Tag %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:126 -#: rhodecode/templates/changelog/changelog_summary_data.html:61 -#: rhodecode/templates/changeset/changeset.html:117 -#: rhodecode/templates/changeset/changeset_range.html:96 +#: kallithea/templates/changelog/changelog.html:135 +#: kallithea/templates/changelog/changelog_summary_data.html:61 +#: kallithea/templates/changeset/changeset.html:105 +#: kallithea/templates/changeset/changeset_range.html:103 #, python-format msgid "Branch %s" msgstr "" -#: rhodecode/templates/changelog/changelog.html:286 +#: kallithea/templates/changelog/changelog.html:299 msgid "There are no changes yet" msgstr "尚未有任何變更" -#: rhodecode/templates/changelog/changelog_details.html:4 -#: rhodecode/templates/changeset/changeset.html:91 +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:76 msgid "Removed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:5 -#: rhodecode/templates/changeset/changeset.html:92 +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:77 msgid "Changed" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:6 -#: rhodecode/templates/changeset/changeset.html:93 +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:78 msgid "Added" msgstr "" -#: rhodecode/templates/changelog/changelog_details.html:8 -#: rhodecode/templates/changelog/changelog_details.html:9 -#: rhodecode/templates/changelog/changelog_details.html:10 -#: rhodecode/templates/changeset/changeset.html:95 -#: rhodecode/templates/changeset/changeset.html:96 -#: rhodecode/templates/changeset/changeset.html:97 +#: kallithea/templates/changelog/changelog_details.html:8 +#: kallithea/templates/changelog/changelog_details.html:9 +#: kallithea/templates/changelog/changelog_details.html:10 +#: kallithea/templates/changeset/changeset.html:80 +#: kallithea/templates/changeset/changeset.html:81 +#: kallithea/templates/changeset/changeset.html:82 #, python-format msgid "Affected %s files" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:6 -#: rhodecode/templates/files/files_add.html:75 -#: rhodecode/templates/files/files_edit.html:61 +#: kallithea/templates/changelog/changelog_summary_data.html:6 +#: kallithea/templates/files/files_add.html:65 +#: kallithea/templates/files/files_delete.html:53 msgid "Commit message" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/changelog/changelog_summary_data.html:7 msgid "Age" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/changelog/changelog_summary_data.html:9 msgid "Refs" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:86 -msgid "Add or upload files directly via RhodeCode" -msgstr "" - -#: rhodecode/templates/changelog/changelog_summary_data.html:89 -#: rhodecode/templates/files/files_add.html:38 -#: rhodecode/templates/files/files_browser.html:31 -msgid "Add new file" -msgstr "" - -#: rhodecode/templates/changelog/changelog_summary_data.html:95 +#: kallithea/templates/changelog/changelog_summary_data.html:86 +msgid "Add or upload files directly via Kallithea" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:89 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:95 msgid "Push new repo" msgstr "" -#: rhodecode/templates/changelog/changelog_summary_data.html:103 +#: kallithea/templates/changelog/changelog_summary_data.html:103 msgid "Existing repository?" msgstr "" -#: rhodecode/templates/changeset/changeset.html:6 +#: kallithea/templates/changeset/changeset.html:6 #, python-format msgid "%s Changeset" msgstr "" -#: rhodecode/templates/changeset/changeset.html:39 -msgid "No parents" -msgstr "" - -#: rhodecode/templates/changeset/changeset.html:49 -msgid "No children" -msgstr "" - -#: rhodecode/templates/changeset/changeset.html:62 -#: rhodecode/templates/changeset/changeset_file_comment.html:20 -#: rhodecode/templates/changeset/changeset_range.html:44 +#: kallithea/templates/changeset/changeset.html:37 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:51 +#: kallithea/templates/changeset/changeset_file_comment.html:41 +#: kallithea/templates/changeset/changeset_range.html:51 msgid "Changeset status" msgstr "" -#: rhodecode/templates/changeset/changeset.html:67 -#: rhodecode/templates/changeset/diff_block.html:22 +#: kallithea/templates/changeset/changeset.html:55 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:52 msgid "Raw diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:68 +#: kallithea/templates/changeset/changeset.html:58 msgid "Patch diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:69 -#: rhodecode/templates/changeset/diff_block.html:23 +#: kallithea/templates/changeset/changeset.html:61 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:55 msgid "Download diff" msgstr "" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "" -#: rhodecode/templates/changeset/changeset.html:73 -#: rhodecode/templates/changeset/changeset_file_comment.html:103 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:111 #, python-format msgid "(%d inline)" msgid_plural "(%d inline)" msgstr[0] "" -#: rhodecode/templates/changeset/changeset.html:103 -#: rhodecode/templates/changeset/changeset_range.html:82 +#: kallithea/templates/changeset/changeset.html:88 +#: kallithea/templates/changeset/changeset_range.html:89 msgid "merge" msgstr "合併" -#: rhodecode/templates/changeset/changeset.html:126 -#: rhodecode/templates/compare/compare_diff.html:40 -#: rhodecode/templates/pullrequests/pullrequest_show.html:113 +#: kallithea/templates/changeset/changeset.html:124 +#: kallithea/templates/compare/compare_diff.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:160 #, python-format msgid "%s file changed" msgid_plural "%s files changed" msgstr[0] "" -#: rhodecode/templates/changeset/changeset.html:128 -#: rhodecode/templates/compare/compare_diff.html:42 -#: rhodecode/templates/pullrequests/pullrequest_show.html:115 +#: kallithea/templates/changeset/changeset.html:126 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:162 #, python-format msgid "%s file changed with %s insertions and %s deletions" msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Showing a huge diff might take some time and resources" msgstr "" -#: rhodecode/templates/changeset/changeset.html:141 -#: rhodecode/templates/changeset/changeset.html:153 -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -#: rhodecode/templates/pullrequests/pullrequest_show.html:131 -#: rhodecode/templates/pullrequests/pullrequest_show.html:195 +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:151 +#: kallithea/templates/compare/compare_diff.html:75 +#: kallithea/templates/compare/compare_diff.html:85 +#: kallithea/templates/pullrequests/pullrequest_show.html:178 +#: kallithea/templates/pullrequests/pullrequest_show.html:202 msgid "Show full diff" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:30 -#, python-format -msgid "Status change on pull request #%s" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:32 +#: kallithea/templates/changeset/changeset.html:214 +#: kallithea/templates/changeset/changeset.html:251 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:23 +#, python-format +msgid "Vote on pull request #%s" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 #, python-format msgid "Comment on pull request #%s" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:55 +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Status change on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Comment on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:63 msgid "Submitting..." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:58 +#: kallithea/templates/changeset/changeset_file_comment.html:66 msgid "Commenting on line {1}." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:59 -#: rhodecode/templates/changeset/changeset_file_comment.html:145 +#: kallithea/templates/changeset/changeset_file_comment.html:67 +#: kallithea/templates/changeset/changeset_file_comment.html:153 #, python-format msgid "Comments parsed using %s syntax with %s support." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:61 -#: rhodecode/templates/changeset/changeset_file_comment.html:147 -msgid "" -"Use @username inside this text to send notification to this RhodeCode user" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:65 -#: rhodecode/templates/changeset/changeset_file_comment.html:152 +#: kallithea/templates/changeset/changeset_file_comment.html:69 +#: kallithea/templates/changeset/changeset_file_comment.html:155 +msgid "Use @username inside this text to send notification to this Kallithea user" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:73 +#: kallithea/templates/changeset/changeset_file_comment.html:166 msgid "Preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:72 -#: rhodecode/templates/changeset/changeset_file_comment.html:170 +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:189 msgid "Comment preview" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:80 -#: rhodecode/templates/changeset/changeset_file_comment.html:177 -#: rhodecode/templates/email_templates/changeset_comment.html:16 -#: rhodecode/templates/email_templates/pull_request_comment.html:16 +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:196 +#: kallithea/templates/email_templates/changeset_comment.html:11 +#: kallithea/templates/email_templates/pull_request_comment.html:16 msgid "Comment" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:81 -msgid "Cancel" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "You need to be logged in to comment." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:96 msgid "Login now" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:92 +#: kallithea/templates/changeset/changeset_file_comment.html:100 msgid "Hide" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.html:149 -msgid "Change status" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.html:179 -msgid "Comment and close" -msgstr "" - -#: rhodecode/templates/changeset/changeset_range.html:5 +#: kallithea/templates/changeset/changeset_file_comment.html:159 +msgid "Vote for pull request status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:161 +msgid "Change changeset status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:179 +msgid "Close (when approved or rejected)" +msgstr "" + +#: kallithea/templates/changeset/changeset_range.html:5 #, python-format msgid "%s Changesets" msgstr "" -#: rhodecode/templates/changeset/changeset_range.html:52 +#: kallithea/templates/changeset/changeset_range.html:59 msgid "Files affected" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:21 +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:46 msgid "Show full diff for this file" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:29 +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:68 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Show full side-by-side diff for this file" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:38 msgid "Show inline comments" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:53 +#: kallithea/templates/changeset/diff_block.html:62 msgid "Show file at latest version in this repo" msgstr "" -#: rhodecode/templates/changeset/diff_block.html:54 +#: kallithea/templates/changeset/diff_block.html:64 msgid "Show file at initial version in this repo" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:4 +#: kallithea/templates/compare/compare_cs.html:4 msgid "No changesets" msgstr "" -#: rhodecode/templates/compare/compare_cs.html:32 +#: kallithea/templates/compare/compare_cs.html:8 msgid "Ancestor" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:5 +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 #, python-format msgid "%s Compare" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:9 +#: kallithea/templates/compare/compare_diff.html:16 msgid "Compare revisions" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:33 -#: rhodecode/templates/pullrequests/pullrequest_show.html:106 +#: kallithea/templates/compare/compare_diff.html:36 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:38 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:45 +msgid "Compare revisions, branches, bookmarks or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:50 +#: kallithea/templates/pullrequests/pullrequest_show.html:153 #, python-format msgid "Showing %s commit" msgid_plural "Showing %s commits" msgstr[0] "" -#: rhodecode/templates/compare/compare_diff.html:48 -#: rhodecode/templates/pullrequests/pullrequest_show.html:121 +#: kallithea/templates/compare/compare_diff.html:65 +#: kallithea/templates/pullrequests/pullrequest_show.html:168 msgid "No files" msgstr "" -#: rhodecode/templates/compare/compare_diff.html:58 -#: rhodecode/templates/compare/compare_diff.html:69 -msgid "confirm to show potentially huge diff" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:54 -#: rhodecode/templates/summary/summary.html:69 +#: kallithea/templates/data_table/_dt_elements.html:63 msgid "Mercurial repository" msgstr "Mercurial 版本庫" -#: rhodecode/templates/data_table/_dt_elements.html:56 -#: rhodecode/templates/summary/summary.html:72 +#: kallithea/templates/data_table/_dt_elements.html:65 msgid "Git repository" msgstr "Git 版本庫" -#: rhodecode/templates/data_table/_dt_elements.html:74 -#, python-format -msgid "Fork of %s" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:88 +#: kallithea/templates/data_table/_dt_elements.html:72 +msgid "Public repository" +msgstr "公開的版本庫" + +#: kallithea/templates/data_table/_dt_elements.html:82 +msgid "Repository creating in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:96 msgid "No changesets yet" msgstr "尚未有任何變更" -#: rhodecode/templates/data_table/_dt_elements.html:95 -#: rhodecode/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:105 #, python-format msgid "Subscribe to %s rss feed" msgstr "訂閱 %s rss" -#: rhodecode/templates/data_table/_dt_elements.html:103 -#: rhodecode/templates/data_table/_dt_elements.html:105 +#: kallithea/templates/data_table/_dt_elements.html:111 +#: kallithea/templates/data_table/_dt_elements.html:113 #, python-format msgid "Subscribe to %s atom feed" msgstr "訂閱 %s atom" -#: rhodecode/templates/data_table/_dt_elements.html:122 -#, python-format -msgid "Confirm to delete this repository: %s" -msgstr "" - -#: rhodecode/templates/data_table/_dt_elements.html:137 -#, python-format -msgid "Confirm to delete this user: %s" -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:4 -#: rhodecode/templates/email_templates/pull_request.html:4 -#: rhodecode/templates/email_templates/pull_request_comment.html:4 -msgid "URL" -msgstr "" - -#: rhodecode/templates/email_templates/changeset_comment.html:6 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:6 #, python-format msgid "%s commented on a %s changeset." msgstr "" -#: rhodecode/templates/email_templates/changeset_comment.html:14 +#: kallithea/templates/email_templates/changeset_comment.html:9 msgid "The changeset status was changed to" msgstr "" -#: rhodecode/templates/email_templates/main.html:8 -msgid "This is a notification from RhodeCode." -msgstr "" - -#: rhodecode/templates/email_templates/password_reset.html:4 +#: kallithea/templates/email_templates/main.html:8 +msgid "This is a notification from Kallithea." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:4 #, python-format msgid "Hello %s" msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:5 +#: kallithea/templates/email_templates/password_reset.html:5 msgid "We received a request to create a new password for your account." msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:6 +#: kallithea/templates/email_templates/password_reset.html:6 msgid "You can generate it by clicking following URL" msgstr "" -#: rhodecode/templates/email_templates/password_reset.html:10 +#: kallithea/templates/email_templates/password_reset.html:10 msgid "Please ignore this email if you did not request a new password ." msgstr "" -#: rhodecode/templates/email_templates/pull_request.html:6 +#: kallithea/templates/email_templates/pull_request.html:6 #, python-format msgid "" -"%s opened a pull request for repository %s and wants you to review changes." -msgstr "" - -#: rhodecode/templates/email_templates/pull_request.html:8 -#: rhodecode/templates/pullrequests/pullrequest.html:34 -#: rhodecode/templates/pullrequests/pullrequest_data.html:14 -#: rhodecode/templates/pullrequests/pullrequest_show.html:25 +"%s opened a pull request for repository %s and wants you to review " +"changes." +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +#: kallithea/templates/pullrequests/pullrequest_show.html:28 msgid "Title" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:6 +#: kallithea/templates/email_templates/pull_request_comment.html:6 #, python-format msgid "%s commented on pull request \"%s\"" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:10 +#: kallithea/templates/email_templates/pull_request_comment.html:10 msgid "Pull request was closed with status" msgstr "" -#: rhodecode/templates/email_templates/pull_request_comment.html:12 +#: kallithea/templates/email_templates/pull_request_comment.html:12 msgid "Pull request changed status" msgstr "" -#: rhodecode/templates/email_templates/registration.html:6 +#: kallithea/templates/email_templates/registration.html:6 msgid "View this user here" msgstr "" -#: rhodecode/templates/errors/error_document.html:55 +#: kallithea/templates/errors/error_document.html:47 #, python-format msgid "You will be redirected to %s in %s seconds" msgstr "" -#: rhodecode/templates/files/file_diff.html:4 +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:22 +#: kallithea/templates/files/file_diff.html:11 +msgid "File diff" +msgstr "檔案差異" + +#: kallithea/templates/files/diff_2way.html:58 +msgid "ignore white space" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:59 +msgid "turn on edit mode" +msgstr "" + +#: kallithea/templates/files/file_diff.html:4 #, python-format msgid "%s File Diff" msgstr "" -#: rhodecode/templates/files/file_diff.html:8 -msgid "File diff" -msgstr "檔案差異" - -#: rhodecode/templates/files/files.html:4 -#: rhodecode/templates/files/files.html:76 +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:84 #, python-format msgid "%s Files" msgstr "" -#: rhodecode/templates/files/files.html:30 -#: rhodecode/templates/files/files_add.html:31 -#: rhodecode/templates/files/files_edit.html:31 -msgid "Branch" -msgstr "" - -#: rhodecode/templates/files/files_add.html:4 +#: kallithea/templates/files/files_add.html:4 #, python-format msgid "%s Files Add" msgstr "" -#: rhodecode/templates/files/files_add.html:19 -msgid "Add file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:43 -msgid "File Name" -msgstr "" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:56 -msgid "or" -msgstr "" - -#: rhodecode/templates/files/files_add.html:47 -#: rhodecode/templates/files/files_add.html:52 -msgid "Upload file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:56 -msgid "Create new file" -msgstr "" - -#: rhodecode/templates/files/files_add.html:61 -#: rhodecode/templates/files/files_edit.html:37 -#: rhodecode/templates/files/files_ypjax.html:3 +#: kallithea/templates/files/files_add.html:25 +msgid "Add new file" +msgstr "" + +#: kallithea/templates/files/files_add.html:45 +#: kallithea/templates/files/files_edit.html:43 +#: kallithea/templates/files/files_ypjax.html:3 msgid "Location" msgstr "位置" -#: rhodecode/templates/files/files_add.html:65 -msgid "use / to separate directories" -msgstr "" - -#: rhodecode/templates/files/files_add.html:79 -#: rhodecode/templates/files/files_edit.html:65 +#: kallithea/templates/files/files_add.html:47 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +#: kallithea/templates/files/files_add.html:53 +msgid "or" +msgstr "" + +#: kallithea/templates/files/files_add.html:49 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:58 +msgid "New file mode" +msgstr "" + +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:57 +#: kallithea/templates/files/files_edit.html:72 msgid "Commit changes" msgstr "遞交修改" -#: rhodecode/templates/files/files_browser.html:13 -msgid "View" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:14 +#: kallithea/templates/files/files_browser.html:13 +msgid "revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:14 msgid "Previous revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:16 +#: kallithea/templates/files/files_browser.html:16 msgid "Next revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:23 +#: kallithea/templates/files/files_browser.html:22 msgid "Follow current branch" msgstr "" -#: rhodecode/templates/files/files_browser.html:27 -msgid "Search file list" -msgstr "" - -#: rhodecode/templates/files/files_browser.html:35 +#: kallithea/templates/files/files_browser.html:25 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:29 msgid "Loading file list..." msgstr "載入檔案列表..." -#: rhodecode/templates/files/files_browser.html:48 +#: kallithea/templates/files/files_browser.html:42 msgid "Size" msgstr "大小" -#: rhodecode/templates/files/files_browser.html:49 +#: kallithea/templates/files/files_browser.html:43 msgid "Mimetype" msgstr "" -#: rhodecode/templates/files/files_browser.html:50 +#: kallithea/templates/files/files_browser.html:44 msgid "Last Revision" msgstr "" -#: rhodecode/templates/files/files_browser.html:51 +#: kallithea/templates/files/files_browser.html:45 msgid "Last modified" msgstr "最後修改" -#: rhodecode/templates/files/files_browser.html:52 +#: kallithea/templates/files/files_browser.html:46 msgid "Last committer" msgstr "最後的遞交者" -#: rhodecode/templates/files/files_edit.html:4 -#, python-format -msgid "%s Files Edit" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:19 +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "" + +#: kallithea/templates/files/files_delete.html:25 +#: kallithea/templates/files/files_delete.html:45 +msgid "Delete file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:25 msgid "Edit file" msgstr "" -#: rhodecode/templates/files/files_edit.html:47 -#: rhodecode/templates/files/files_source.html:23 -msgid "Show annotation" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:49 -#: rhodecode/templates/files/files_source.html:26 -msgid "Download as raw" -msgstr "" - -#: rhodecode/templates/files/files_edit.html:52 +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:55 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:58 msgid "Source" msgstr "" -#: rhodecode/templates/files/files_edit.html:57 +#: kallithea/templates/files/files_edit.html:63 msgid "Editing file" msgstr "" -#: rhodecode/templates/files/files_history_box.html:2 -msgid "History" -msgstr "歷史" - -#: rhodecode/templates/files/files_history_box.html:9 -msgid "Diff to revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:10 -msgid "Show at revision" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:11 -msgid "Show full history" -msgstr "" - -#: rhodecode/templates/files/files_history_box.html:16 +#: kallithea/templates/files/files_edit.html:68 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 #, python-format msgid "%s author" msgid_plural "%s authors" msgstr[0] "" -#: rhodecode/templates/files/files_source.html:6 -msgid "Load file history" -msgstr "" - -#: rhodecode/templates/files/files_source.html:21 -msgid "Show source" -msgstr "" - -#: rhodecode/templates/files/files_source.html:29 -#, python-format -msgid "Edit on branch:%s" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 -msgid "Edit on branch:?" -msgstr "" - -#: rhodecode/templates/files/files_source.html:31 +#: kallithea/templates/files/files_source.html:7 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:8 +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:11 +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:30 +msgid "Show Source" +msgstr "" + +#: kallithea/templates/files/files_source.html:38 +#, python-format +msgid "Edit on Branch:%s" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Editing binary files not allowed" +msgstr "" + +#: kallithea/templates/files/files_source.html:44 msgid "Editing files allowed only when on branch head revision" msgstr "" -#: rhodecode/templates/files/files_source.html:46 +#: kallithea/templates/files/files_source.html:45 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:61 #, python-format msgid "Binary file (%s)" msgstr "二進位檔 (%s)" -#: rhodecode/templates/files/files_source.html:55 +#: kallithea/templates/files/files_source.html:71 msgid "File is too big to display" msgstr "顯示的檔案太大" -#: rhodecode/templates/files/files_ypjax.html:5 +#: kallithea/templates/files/files_ypjax.html:5 msgid "annotation" msgstr "" -#: rhodecode/templates/files/files_ypjax.html:15 -msgid "Go back" -msgstr "" - -#: rhodecode/templates/files/files_ypjax.html:16 +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:24 msgid "No files at given path" msgstr "" -#: rhodecode/templates/followers/followers.html:5 +#: kallithea/templates/followers/followers.html:5 #, python-format msgid "%s Followers" msgstr "" -#: rhodecode/templates/followers/followers.html:9 -#: rhodecode/templates/summary/summary.html:183 -#: rhodecode/templates/summary/summary.html:184 +#: kallithea/templates/followers/followers.html:12 +#: kallithea/templates/summary/summary.html:149 +#: kallithea/templates/summary/summary.html:150 msgid "Followers" msgstr "追蹤者" -#: rhodecode/templates/followers/followers_data.html:12 +#: kallithea/templates/followers/followers_data.html:12 msgid "Started following -" msgstr "" -#: rhodecode/templates/forks/fork.html:5 -#, python-format -msgid "%s Fork" -msgstr "" - -#: rhodecode/templates/forks/fork.html:28 +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:30 msgid "Fork name" msgstr "分支名稱" -#: rhodecode/templates/forks/fork.html:65 +#: kallithea/templates/forks/fork.html:71 msgid "Private" msgstr "私有" -#: rhodecode/templates/forks/fork.html:74 +#: kallithea/templates/forks/fork.html:80 msgid "Copy permissions" msgstr "" -#: rhodecode/templates/forks/fork.html:78 +#: kallithea/templates/forks/fork.html:84 msgid "Copy permissions from forked repository" msgstr "" -#: rhodecode/templates/forks/fork.html:84 +#: kallithea/templates/forks/fork.html:90 msgid "Update after clone" msgstr "" -#: rhodecode/templates/forks/fork.html:88 +#: kallithea/templates/forks/fork.html:94 msgid "Checkout source after making a clone" msgstr "" -#: rhodecode/templates/forks/fork.html:93 -msgid "Fork this repository" -msgstr "" - -#: rhodecode/templates/forks/forks.html:5 +#: kallithea/templates/forks/fork.html:99 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 #, python-format msgid "%s Forks" msgstr "" -#: rhodecode/templates/forks/forks.html:9 -#: rhodecode/templates/summary/summary.html:189 -#: rhodecode/templates/summary/summary.html:190 +#: kallithea/templates/forks/forks.html:12 +#: kallithea/templates/summary/summary.html:155 +#: kallithea/templates/summary/summary.html:156 msgid "Forks" msgstr "" -#: rhodecode/templates/forks/forks_data.html:17 +#: kallithea/templates/forks/forks_data.html:17 msgid "Forked" msgstr "" -#: rhodecode/templates/forks/forks_data.html:42 +#: kallithea/templates/forks/forks_data.html:42 msgid "There are no forks yet" msgstr "尚未有任何 fork" -#: rhodecode/templates/journal/journal.html:21 +#: kallithea/templates/journal/journal.html:24 msgid "ATOM journal feed" msgstr "" -#: rhodecode/templates/journal/journal.html:22 +#: kallithea/templates/journal/journal.html:25 msgid "RSS journal feed" msgstr "" -#: rhodecode/templates/journal/journal.html:32 -msgid "Refresh" -msgstr "" - -#: rhodecode/templates/journal/journal.html:35 -#: rhodecode/templates/journal/public_journal.html:24 -msgid "ATOM feed" -msgstr "" - -#: rhodecode/templates/journal/journal.html:51 -msgid "Watched" -msgstr "" - -#: rhodecode/templates/journal/journal_data.html:55 +#: kallithea/templates/journal/journal.html:57 +msgid "My repos" +msgstr "" + +#: kallithea/templates/journal/journal_data.html:55 msgid "No entries yet" msgstr "" -#: rhodecode/templates/journal/public_journal.html:4 -#: rhodecode/templates/journal/public_journal.html:21 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:24 msgid "Public Journal" msgstr "開放日誌" -#: rhodecode/templates/journal/public_journal.html:13 +#: kallithea/templates/journal/public_journal.html:16 msgid "ATOM public journal feed" msgstr "" -#: rhodecode/templates/journal/public_journal.html:14 +#: kallithea/templates/journal/public_journal.html:17 msgid "RSS public journal feed" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:4 -#: rhodecode/templates/pullrequests/pullrequest.html:8 +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 msgid "New pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:25 -msgid "Create new pull request" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.html:47 +#: kallithea/templates/pullrequests/pullrequest.html:44 msgid "Write a short description on this pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:53 +#: kallithea/templates/pullrequests/pullrequest.html:50 msgid "Changeset flow" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:60 -#: rhodecode/templates/pullrequests/pullrequest_show.html:65 +#: kallithea/templates/pullrequests/pullrequest.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:68 msgid "Origin repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:85 -msgid "Send pull request" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.html:94 -#: rhodecode/templates/pullrequests/pullrequest_show.html:137 +#: kallithea/templates/pullrequests/pullrequest.html:82 +msgid "Send Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:91 +#: kallithea/templates/pullrequests/pullrequest_show.html:104 msgid "Pull request reviewers" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:103 -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 +#: kallithea/templates/pullrequests/pullrequest.html:100 +#: kallithea/templates/pullrequests/pullrequest_show.html:116 msgid "owner" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:115 +#: kallithea/templates/pullrequests/pullrequest.html:114 msgid "Add reviewer to this pull request." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:129 +#: kallithea/templates/pullrequests/pullrequest.html:128 msgid "Detailed compare view" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.html:150 +#: kallithea/templates/pullrequests/pullrequest.html:149 msgid "Destination repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:4 +#: kallithea/templates/pullrequests/pullrequest_show.html:4 #, python-format msgid "%s Pull Request #%s" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:35 +#: kallithea/templates/pullrequests/pullrequest_show.html:36 msgid "Review status" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:40 -msgid "Pull request status" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:42 +#: kallithea/templates/pullrequests/pullrequest_show.html:43 +msgid "Pull request status calculated from votes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:56 msgid "Still not reviewed by" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:57 +#: kallithea/templates/pullrequests/pullrequest_show.html:60 #, python-format msgid "%d reviewer" msgid_plural "%d reviewers" msgstr[0] "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:62 msgid "Pull request was reviewed by all reviewers" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:89 -msgid "Created on" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:102 +#: kallithea/templates/pullrequests/pullrequest_show.html:77 +#: kallithea/templates/pullrequests/pullrequest_show.html:79 +msgid "Pull changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:116 +msgid "reviewer" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:133 +msgid "Add or remove reviewer to this pull request." +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:137 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:149 msgid "Compare view" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.html:149 -msgid "reviewer" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:164 -msgid "Add or remove reviewer to this pull request." -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.html:168 -msgid "Save changes" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show_all.html:4 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 #, python-format msgid "%s Pull Requests" msgstr "" -#: rhodecode/templates/search/search.html:6 -msgid "Search repository" -msgstr "" - -#: rhodecode/templates/search/search.html:8 -#: rhodecode/templates/search/search.html:16 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:12 +#, python-format +msgid "Pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:14 +#, python-format +msgid "Pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:38 +#, python-format +msgid "Show pull requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:40 +#, python-format +msgid "Show pull requests from %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:50 +msgid "Hide closed pull requests" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:52 +msgid "Show closed pull requests too" +msgstr "" + +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:19 msgid "Search in all repositories" msgstr "" -#: rhodecode/templates/search/search.html:50 +#: kallithea/templates/search/search.html:53 msgid "Search term" msgstr "搜尋關鍵字" -#: rhodecode/templates/search/search.html:62 +#: kallithea/templates/search/search.html:65 msgid "Search in" msgstr "搜尋範圍" -#: rhodecode/templates/search/search.html:65 +#: kallithea/templates/search/search.html:68 msgid "File contents" msgstr "文件內容" -#: rhodecode/templates/search/search.html:66 +#: kallithea/templates/search/search.html:69 msgid "Commit messages" msgstr "" -#: rhodecode/templates/search/search.html:67 +#: kallithea/templates/search/search.html:70 msgid "File names" msgstr "檔案名稱" -#: rhodecode/templates/search/search_commit.html:35 -#: rhodecode/templates/search/search_content.html:21 -#: rhodecode/templates/search/search_path.html:15 +#: kallithea/templates/search/search_commit.html:35 +#: kallithea/templates/search/search_content.html:21 +#: kallithea/templates/search/search_path.html:15 msgid "Permission denied" msgstr "權限不足" -#: rhodecode/templates/summary/summary.html:4 -#, python-format -msgid "%s Summary" -msgstr "" - -#: rhodecode/templates/summary/summary.html:16 +#: kallithea/templates/summary/statistics.html:4 +#, python-format +msgid "%s Statistics" +msgstr "" + +#: kallithea/templates/summary/statistics.html:19 +#: kallithea/templates/summary/summary.html:42 #, python-format msgid "%s ATOM feed" msgstr "" -#: rhodecode/templates/summary/summary.html:17 +#: kallithea/templates/summary/statistics.html:20 +#: kallithea/templates/summary/summary.html:43 #, python-format msgid "%s RSS feed" msgstr "" -#: rhodecode/templates/summary/summary.html:62 +#: kallithea/templates/summary/statistics.html:39 +#: kallithea/templates/summary/summary.html:107 +#: kallithea/templates/summary/summary.html:123 +msgid "Enable" +msgstr "" + +#: kallithea/templates/summary/statistics.html:42 +msgid "Stats gathered: " +msgstr "" + +#: kallithea/templates/summary/statistics.html:91 +#: kallithea/templates/summary/summary.html:354 +msgid "files" +msgstr "檔案" + +#: kallithea/templates/summary/statistics.html:115 +#: kallithea/templates/summary/summary.html:378 +msgid "Show more" +msgstr "" + +#: kallithea/templates/summary/statistics.html:392 +msgid "commits" +msgstr "遞交" + +#: kallithea/templates/summary/statistics.html:393 +msgid "files added" +msgstr "多個檔案新增" + +#: kallithea/templates/summary/statistics.html:394 +msgid "files changed" +msgstr "多個檔案修改" + +#: kallithea/templates/summary/statistics.html:395 +msgid "files removed" +msgstr "移除多個檔案" + +#: kallithea/templates/summary/statistics.html:397 +msgid "commit" +msgstr "遞交" + +#: kallithea/templates/summary/statistics.html:398 +msgid "file added" +msgstr "檔案新增" + +#: kallithea/templates/summary/statistics.html:399 +msgid "file changed" +msgstr "檔案修改" + +#: kallithea/templates/summary/statistics.html:400 +msgid "file removed" +msgstr "移除檔案" + +#: kallithea/templates/summary/summary.html:4 +#, python-format +msgid "%s Summary" +msgstr "" + +#: kallithea/templates/summary/summary.html:16 #, python-format msgid "Repository locked by %s" msgstr "" -#: rhodecode/templates/summary/summary.html:64 +#: kallithea/templates/summary/summary.html:18 msgid "Repository unlocked" msgstr "" -#: rhodecode/templates/summary/summary.html:83 -#, python-format -msgid "Non changable ID %s" -msgstr "" - -#: rhodecode/templates/summary/summary.html:88 -msgid "Public" -msgstr "" - -#: rhodecode/templates/summary/summary.html:88 -#: rhodecode/templates/summary/summary.html:89 -msgid "Fork of" -msgstr "" - -#: rhodecode/templates/summary/summary.html:97 -msgid "Remote clone" -msgstr "" - -#: rhodecode/templates/summary/summary.html:117 -msgid "Contact" -msgstr "聯絡方式" - -#: rhodecode/templates/summary/summary.html:131 +#: kallithea/templates/summary/summary.html:76 msgid "Clone url" msgstr "複製連結" -#: rhodecode/templates/summary/summary.html:136 +#: kallithea/templates/summary/summary.html:81 msgid "Show by Name" msgstr "" -#: rhodecode/templates/summary/summary.html:137 +#: kallithea/templates/summary/summary.html:82 msgid "Show by ID" msgstr "" -#: rhodecode/templates/summary/summary.html:143 +#: kallithea/templates/summary/summary.html:99 msgid "Trending files" msgstr "" -#: rhodecode/templates/summary/summary.html:151 -#: rhodecode/templates/summary/summary.html:167 -msgid "Enable" -msgstr "" - -#: rhodecode/templates/summary/summary.html:159 +#: kallithea/templates/summary/summary.html:115 msgid "Download" msgstr "下載" -#: rhodecode/templates/summary/summary.html:163 +#: kallithea/templates/summary/summary.html:119 msgid "There are no downloads yet" msgstr "沒有任何下載" -#: rhodecode/templates/summary/summary.html:165 +#: kallithea/templates/summary/summary.html:121 msgid "Downloads are disabled for this repository" msgstr "這個版本庫的下載已停用" -#: rhodecode/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:127 msgid "Download as zip" msgstr "" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "Check this to download archive with subrepos" msgstr "" -#: rhodecode/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:132 msgid "with subrepos" msgstr "" -#: rhodecode/templates/summary/summary.html:197 +#: kallithea/templates/summary/summary.html:163 msgid "Repository Size" msgstr "" -#: rhodecode/templates/summary/summary.html:204 -#: rhodecode/templates/summary/summary.html:206 +#: kallithea/templates/summary/summary.html:170 +#: kallithea/templates/summary/summary.html:172 msgid "Feed" msgstr "" -#: rhodecode/templates/summary/summary.html:224 -msgid "Commit activity by day / author" -msgstr "" - -#: rhodecode/templates/summary/summary.html:232 -msgid "enable" -msgstr "啟用" - -#: rhodecode/templates/summary/summary.html:235 -msgid "Stats gathered: " -msgstr "" - -#: rhodecode/templates/summary/summary.html:256 +#: kallithea/templates/summary/summary.html:193 msgid "Latest changes" msgstr "" -#: rhodecode/templates/summary/summary.html:258 +#: kallithea/templates/summary/summary.html:195 msgid "Quick start" msgstr "" -#: rhodecode/templates/summary/summary.html:272 -#, python-format -msgid "Readme file from revision %s" -msgstr "" - -#: rhodecode/templates/summary/summary.html:332 +#: kallithea/templates/summary/summary.html:209 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:299 #, python-format msgid "Download %s as %s" msgstr "下載 %s 為 %s" -#: rhodecode/templates/summary/summary.html:379 -msgid "files" -msgstr "檔案" - -#: rhodecode/templates/summary/summary.html:689 -msgid "commits" -msgstr "遞交" - -#: rhodecode/templates/summary/summary.html:690 -msgid "files added" -msgstr "多個檔案新增" - -#: rhodecode/templates/summary/summary.html:691 -msgid "files changed" -msgstr "多個檔案修改" - -#: rhodecode/templates/summary/summary.html:692 -msgid "files removed" -msgstr "移除多個檔案" - -#: rhodecode/templates/summary/summary.html:694 -msgid "commit" -msgstr "遞交" - -#: rhodecode/templates/summary/summary.html:695 -msgid "file added" -msgstr "檔案新增" - -#: rhodecode/templates/summary/summary.html:696 -msgid "file changed" -msgstr "檔案修改" - -#: rhodecode/templates/summary/summary.html:697 -msgid "file removed" -msgstr "移除檔案" - -#: rhodecode/templates/tags/tags.html:5 +#: kallithea/templates/tags/tags.html:5 #, python-format msgid "%s Tags" msgstr "" -#: rhodecode/templates/tags/tags.html:26 +#: kallithea/templates/tags/tags.html:29 msgid "Compare tags" msgstr "" + diff --git a/rhodecode/lib/__init__.py b/kallithea/lib/__init__.py rename from rhodecode/lib/__init__.py rename to kallithea/lib/__init__.py --- a/rhodecode/lib/__init__.py +++ b/kallithea/lib/__init__.py @@ -1,6 +1,32 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.lib +~~~~~~~~~~~~~ + +Kallithea libs + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Oct 06, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import os - def get_current_revision(quiet=False): """ Returns tuple of (number, id) from repository containing this package @@ -10,8 +36,8 @@ def get_current_revision(quiet=False): """ try: - from rhodecode.lib.vcs import get_repo - from rhodecode.lib.vcs.utils.helpers import get_scm + from kallithea.lib.vcs import get_repo + from kallithea.lib.vcs.utils.helpers import get_scm repopath = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) scm = get_scm(repopath)[0] @@ -21,7 +47,7 @@ def get_current_revision(quiet=False): return (cur_rev.revision, cur_rev.short_id) except Exception, err: if not quiet: - print ("WARNING: Cannot retrieve rhodecode's revision. " + print ("WARNING: Cannot retrieve kallithea's revision. " "disregard this if you don't know what that means. " "Original error was: %s" % err) return None diff --git a/rhodecode/lib/annotate.py b/kallithea/lib/annotate.py rename from rhodecode/lib/annotate.py rename to kallithea/lib/annotate.py --- a/rhodecode/lib/annotate.py +++ b/kallithea/lib/annotate.py @@ -1,19 +1,34 @@ # -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . """ - rhodecode.lib.annotate - ~~~~~~~~~~~~~~~~~~~~~~ +kallithea.lib.annotate +~~~~~~~~~~~~~~~~~~~~~~ - Anontation library for usage in rhodecode, previously part of vcs +Anontation library for usage in kallithea, previously part of vcs - :created_on: Dec 4, 2011 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Dec 4, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. """ + import StringIO -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.nodes import FileNode +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.nodes import FileNode from pygments.formatters import HtmlFormatter from pygments import highlight @@ -33,7 +48,7 @@ def annotate_highlight(filenode, annotat :param headers: dictionary with headers (keys are whats in ``order`` parameter) """ - from rhodecode.lib.utils import get_custom_lexer + from kallithea.lib.utils import get_custom_lexer options['linenos'] = True formatter = AnnotateHtmlFormatter(filenode=filenode, order=order, headers=headers, diff --git a/rhodecode/lib/app_globals.py b/kallithea/lib/app_globals.py rename from rhodecode/lib/app_globals.py rename to kallithea/lib/app_globals.py --- a/rhodecode/lib/app_globals.py +++ b/kallithea/lib/app_globals.py @@ -1,13 +1,39 @@ -"""The application's Globals object""" +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +kallithea.lib.app_globals +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The application's Globals object + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Oct 06, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" from beaker.cache import CacheManager from beaker.util import parse_cache_config_options class Globals(object): - """Globals acts as a container for objects available throughout the + """ + Globals acts as a container for objects available throughout the life of the application - """ def __init__(self, config): diff --git a/rhodecode/lib/auth.py b/kallithea/lib/auth.py rename from rhodecode/lib/auth.py rename to kallithea/lib/auth.py --- a/rhodecode/lib/auth.py +++ b/kallithea/lib/auth.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.auth - ~~~~~~~~~~~~~~~~~~ - - authentication and permission libraries - - :created_on: Apr 4, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,34 +11,54 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.auth +~~~~~~~~~~~~~~~~~~ +authentication and permission libraries + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 4, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" +from __future__ import with_statement +import time import random import logging import traceback import hashlib +import itertools +import collections from tempfile import _RandomNameSequence from decorator import decorator -from pylons import config, url, request +from pylons import url, request from pylons.controllers.util import abort, redirect from pylons.i18n.translation import _ +from sqlalchemy import or_ from sqlalchemy.orm.exc import ObjectDeletedError - -from rhodecode import __platform__, is_windows, is_unix -from rhodecode.model.meta import Session +from sqlalchemy.orm import joinedload -from rhodecode.lib.utils2 import str2bool, safe_unicode, aslist -from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError,\ - LdapImportError -from rhodecode.lib.utils import get_repo_slug, get_repos_group_slug,\ - get_user_group_slug -from rhodecode.lib.auth_ldap import AuthLdap +from kallithea import __platform__, is_windows, is_unix +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.model import meta +from kallithea.model.meta import Session +from kallithea.model.user import UserModel +from kallithea.model.db import User, Repository, Permission, \ + UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \ + RepoGroup, UserGroupRepoGroupToPerm, UserIpMap, UserGroupUserGroupToPerm, \ + UserGroup, UserApiKeys -from rhodecode.model import meta -from rhodecode.model.user import UserModel -from rhodecode.model.db import Permission, RhodeCodeSetting, User, UserIpMap -from rhodecode.lib.caching_query import FromCache +from kallithea.lib.utils2 import safe_unicode, aslist +from kallithea.lib.utils import get_repo_slug, get_repo_group_slug, \ + get_user_group_slug, conditional_cache +from kallithea.lib.caching_query import FromCache + +from beaker.cache import cache_region log = logging.getLogger(__name__) @@ -86,7 +95,7 @@ class PasswordGenerator(object): return self.passwd -class RhodeCodeCrypto(object): +class KallitheaCrypto(object): @classmethod def hash_string(cls, str_): @@ -128,11 +137,11 @@ class RhodeCodeCrypto(object): def get_crypt_password(password): - return RhodeCodeCrypto.hash_string(password) + return KallitheaCrypto.hash_string(password) def check_password(password, hashed): - return RhodeCodeCrypto.hash_check(password, hashed) + return KallitheaCrypto.hash_check(password, hashed) def generate_api_key(str_, salt=None): @@ -149,166 +158,6 @@ def generate_api_key(str_, salt=None): return hashlib.sha1(str_ + salt).hexdigest() -def authfunc(environ, username, password): - """ - Dummy authentication wrapper function used in Mercurial and Git for - access control. - - :param environ: needed only for using in Basic auth - """ - return authenticate(username, password) - - -def authenticate(username, password): - """ - Authentication function used for access control, - firstly checks for db authentication then if ldap is enabled for ldap - authentication, also creates ldap user if not in database - - :param username: username - :param password: password - """ - - user_model = UserModel() - user = User.get_by_username(username) - - log.debug('Authenticating user using RhodeCode account') - if user is not None and not user.ldap_dn: - if user.active: - if user.username == 'default' and user.active: - log.info('user %s authenticated correctly as anonymous user' % - username) - return True - - elif user.username == username and check_password(password, - user.password): - log.info('user %s authenticated correctly' % username) - return True - else: - log.warning('user %s tried auth but is disabled' % username) - - else: - log.debug('Regular authentication failed') - user_obj = User.get_by_username(username, case_insensitive=True) - - if user_obj is not None and not user_obj.ldap_dn: - log.debug('this user already exists as non ldap') - return False - - ldap_settings = RhodeCodeSetting.get_ldap_settings() - #====================================================================== - # FALLBACK TO LDAP AUTH IF ENABLE - #====================================================================== - if str2bool(ldap_settings.get('ldap_active')): - log.debug("Authenticating user using ldap") - kwargs = { - 'server': ldap_settings.get('ldap_host', ''), - 'base_dn': ldap_settings.get('ldap_base_dn', ''), - 'port': ldap_settings.get('ldap_port'), - 'bind_dn': ldap_settings.get('ldap_dn_user'), - 'bind_pass': ldap_settings.get('ldap_dn_pass'), - 'tls_kind': ldap_settings.get('ldap_tls_kind'), - 'tls_reqcert': ldap_settings.get('ldap_tls_reqcert'), - 'ldap_filter': ldap_settings.get('ldap_filter'), - 'search_scope': ldap_settings.get('ldap_search_scope'), - 'attr_login': ldap_settings.get('ldap_attr_login'), - 'ldap_version': 3, - } - log.debug('Checking for ldap authentication') - try: - aldap = AuthLdap(**kwargs) - (user_dn, ldap_attrs) = aldap.authenticate_ldap(username, - password) - log.debug('Got ldap DN response %s' % user_dn) - - get_ldap_attr = lambda k: ldap_attrs.get(ldap_settings\ - .get(k), [''])[0] - - user_attrs = { - 'name': safe_unicode(get_ldap_attr('ldap_attr_firstname')), - 'lastname': safe_unicode(get_ldap_attr('ldap_attr_lastname')), - 'email': get_ldap_attr('ldap_attr_email'), - 'active': 'hg.extern_activate.auto' in User.get_default_user()\ - .AuthUser.permissions['global'] - } - - # don't store LDAP password since we don't need it. Override - # with some random generated password - _password = PasswordGenerator().gen_password(length=8) - # create this user on the fly if it doesn't exist in rhodecode - # database - if user_model.create_ldap(username, _password, user_dn, - user_attrs): - log.info('created new ldap user %s' % username) - - Session().commit() - return True - except (LdapUsernameError, LdapPasswordError, LdapImportError): - pass - except (Exception,): - log.error(traceback.format_exc()) - pass - return False - - -def login_container_auth(username): - user = User.get_by_username(username) - if user is None: - user_attrs = { - 'name': username, - 'lastname': None, - 'email': None, - 'active': 'hg.extern_activate.auto' in User.get_default_user()\ - .AuthUser.permissions['global'] - } - user = UserModel().create_for_container_auth(username, user_attrs) - if not user: - return None - log.info('User %s was created by container authentication' % username) - - if not user.active: - return None - - user.update_lastlogin() - Session().commit() - - log.debug('User %s is now logged in by container authentication', - user.username) - return user - - -def get_container_username(environ, config, clean_username=False): - """ - Gets the container_auth username (or email). It tries to get username - from REMOTE_USER if container_auth_enabled is enabled, if that fails - it tries to get username from HTTP_X_FORWARDED_USER if proxypass_auth_enabled - is enabled. clean_username extracts the username from this data if it's - having @ in it. - - :param environ: - :param config: - :param clean_username: - """ - username = None - - if str2bool(config.get('container_auth_enabled', False)): - from paste.httpheaders import REMOTE_USER - username = REMOTE_USER(environ) - log.debug('extracted REMOTE_USER:%s' % (username)) - - if not username and str2bool(config.get('proxypass_auth_enabled', False)): - username = environ.get('HTTP_X_FORWARDED_USER') - log.debug('extracted HTTP_X_FORWARDED_USER:%s' % (username)) - - if username and clean_username: - # Removing realm and domain from username - username = username.partition('@')[0] - username = username.rpartition('\\')[2] - log.debug('Received username %s from container' % username) - - return username - - class CookieStoreWrapper(object): def __init__(self, cookie_store): @@ -324,60 +173,361 @@ class CookieStoreWrapper(object): return self.cookie_store.__dict__.get(key, other) -class AuthUser(object): + +def _cached_perms_data(user_id, user_is_admin, user_inherit_default_permissions, + explicit, algo): + RK = 'repositories' + GK = 'repositories_groups' + UK = 'user_groups' + GLOBAL = 'global' + PERM_WEIGHTS = Permission.PERM_WEIGHTS + permissions = {RK: {}, GK: {}, UK: {}, GLOBAL: set()} + + def _choose_perm(new_perm, cur_perm): + new_perm_val = PERM_WEIGHTS[new_perm] + cur_perm_val = PERM_WEIGHTS[cur_perm] + if algo == 'higherwin': + if new_perm_val > cur_perm_val: + return new_perm + return cur_perm + elif algo == 'lowerwin': + if new_perm_val < cur_perm_val: + return new_perm + return cur_perm + + #====================================================================== + # fetch default permissions + #====================================================================== + default_user = User.get_by_username('default', cache=True) + default_user_id = default_user.user_id + + default_repo_perms = Permission.get_default_perms(default_user_id) + default_repo_groups_perms = Permission.get_default_group_perms(default_user_id) + default_user_group_perms = Permission.get_default_user_group_perms(default_user_id) + + if user_is_admin: + #================================================================== + # admin user have all default rights for repositories + # and groups set to admin + #================================================================== + permissions[GLOBAL].add('hg.admin') + permissions[GLOBAL].add('hg.create.write_on_repogroup.true') + + # repositories + for perm in default_repo_perms: + r_k = perm.UserRepoToPerm.repository.repo_name + p = 'repository.admin' + permissions[RK][r_k] = p + + # repository groups + for perm in default_repo_groups_perms: + rg_k = perm.UserRepoGroupToPerm.group.group_name + p = 'group.admin' + permissions[GK][rg_k] = p + + # user groups + for perm in default_user_group_perms: + u_k = perm.UserUserGroupToPerm.user_group.users_group_name + p = 'usergroup.admin' + permissions[UK][u_k] = p + return permissions + + #================================================================== + # SET DEFAULTS GLOBAL, REPOS, REPOSITORY GROUPS + #================================================================== + uid = user_id + + # default global permissions taken fron the default user + default_global_perms = UserToPerm.query()\ + .filter(UserToPerm.user_id == default_user_id)\ + .options(joinedload(UserToPerm.permission)) + + for perm in default_global_perms: + permissions[GLOBAL].add(perm.permission.permission_name) + + # defaults for repositories, taken from default user + for perm in default_repo_perms: + r_k = perm.UserRepoToPerm.repository.repo_name + if perm.Repository.private and not (perm.Repository.user_id == uid): + # disable defaults for private repos, + p = 'repository.none' + elif perm.Repository.user_id == uid: + # set admin if owner + p = 'repository.admin' + else: + p = perm.Permission.permission_name + + permissions[RK][r_k] = p + + # defaults for repository groups taken from default user permission + # on given group + for perm in default_repo_groups_perms: + rg_k = perm.UserRepoGroupToPerm.group.group_name + p = perm.Permission.permission_name + permissions[GK][rg_k] = p + + # defaults for user groups taken from default user permission + # on given user group + for perm in default_user_group_perms: + u_k = perm.UserUserGroupToPerm.user_group.users_group_name + p = perm.Permission.permission_name + permissions[UK][u_k] = p + + #====================================================================== + # !! OVERRIDE GLOBALS !! with user permissions if any found + #====================================================================== + # those can be configured from groups or users explicitly + _configurable = set([ + 'hg.fork.none', 'hg.fork.repository', + 'hg.create.none', 'hg.create.repository', + 'hg.usergroup.create.false', 'hg.usergroup.create.true' + ]) + + # USER GROUPS comes first + # user group global permissions + user_perms_from_users_groups = Session().query(UserGroupToPerm)\ + .options(joinedload(UserGroupToPerm.permission))\ + .join((UserGroupMember, UserGroupToPerm.users_group_id == + UserGroupMember.users_group_id))\ + .filter(UserGroupMember.user_id == uid)\ + .order_by(UserGroupToPerm.users_group_id)\ + .all() + # need to group here by groups since user can be in more than + # one group + _grouped = [[x, list(y)] for x, y in + itertools.groupby(user_perms_from_users_groups, + lambda x:x.users_group)] + for gr, perms in _grouped: + # since user can be in multiple groups iterate over them and + # select the lowest permissions first (more explicit) + ##TODO: do this^^ + if not gr.inherit_default_permissions: + # NEED TO IGNORE all configurable permissions and + # replace them with explicitly set + permissions[GLOBAL] = permissions[GLOBAL]\ + .difference(_configurable) + for perm in perms: + permissions[GLOBAL].add(perm.permission.permission_name) + + # user specific global permissions + user_perms = Session().query(UserToPerm)\ + .options(joinedload(UserToPerm.permission))\ + .filter(UserToPerm.user_id == uid).all() + + if not user_inherit_default_permissions: + # NEED TO IGNORE all configurable permissions and + # replace them with explicitly set + permissions[GLOBAL] = permissions[GLOBAL]\ + .difference(_configurable) + + for perm in user_perms: + permissions[GLOBAL].add(perm.permission.permission_name) + ## END GLOBAL PERMISSIONS + + #====================================================================== + # !! PERMISSIONS FOR REPOSITORIES !! + #====================================================================== + #====================================================================== + # check if user is part of user groups for this repository and + # fill in his permission from it. _choose_perm decides of which + # permission should be selected based on selected method + #====================================================================== + + # user group for repositories permissions + user_repo_perms_from_users_groups = \ + Session().query(UserGroupRepoToPerm, Permission, Repository,)\ + .join((Repository, UserGroupRepoToPerm.repository_id == + Repository.repo_id))\ + .join((Permission, UserGroupRepoToPerm.permission_id == + Permission.permission_id))\ + .join((UserGroupMember, UserGroupRepoToPerm.users_group_id == + UserGroupMember.users_group_id))\ + .filter(UserGroupMember.user_id == uid)\ + .all() + + multiple_counter = collections.defaultdict(int) + for perm in user_repo_perms_from_users_groups: + r_k = perm.UserGroupRepoToPerm.repository.repo_name + multiple_counter[r_k] += 1 + p = perm.Permission.permission_name + cur_perm = permissions[RK][r_k] + + if perm.Repository.user_id == uid: + # set admin if owner + p = 'repository.admin' + else: + if multiple_counter[r_k] > 1: + p = _choose_perm(p, cur_perm) + permissions[RK][r_k] = p + + # user explicit permissions for repositories, overrides any specified + # by the group permission + user_repo_perms = Permission.get_default_perms(uid) + for perm in user_repo_perms: + r_k = perm.UserRepoToPerm.repository.repo_name + cur_perm = permissions[RK][r_k] + # set admin if owner + if perm.Repository.user_id == uid: + p = 'repository.admin' + else: + p = perm.Permission.permission_name + if not explicit: + p = _choose_perm(p, cur_perm) + permissions[RK][r_k] = p + + #====================================================================== + # !! PERMISSIONS FOR REPOSITORY GROUPS !! + #====================================================================== + #====================================================================== + # check if user is part of user groups for this repository groups and + # fill in his permission from it. _choose_perm decides of which + # permission should be selected based on selected method + #====================================================================== + # user group for repo groups permissions + user_repo_group_perms_from_users_groups = \ + Session().query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\ + .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\ + .join((Permission, UserGroupRepoGroupToPerm.permission_id + == Permission.permission_id))\ + .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id + == UserGroupMember.users_group_id))\ + .filter(UserGroupMember.user_id == uid)\ + .all() + + multiple_counter = collections.defaultdict(int) + for perm in user_repo_group_perms_from_users_groups: + g_k = perm.UserGroupRepoGroupToPerm.group.group_name + multiple_counter[g_k] += 1 + p = perm.Permission.permission_name + cur_perm = permissions[GK][g_k] + if multiple_counter[g_k] > 1: + p = _choose_perm(p, cur_perm) + permissions[GK][g_k] = p + + # user explicit permissions for repository groups + user_repo_groups_perms = Permission.get_default_group_perms(uid) + for perm in user_repo_groups_perms: + rg_k = perm.UserRepoGroupToPerm.group.group_name + p = perm.Permission.permission_name + cur_perm = permissions[GK][rg_k] + if not explicit: + p = _choose_perm(p, cur_perm) + permissions[GK][rg_k] = p + + #====================================================================== + # !! PERMISSIONS FOR USER GROUPS !! + #====================================================================== + # user group for user group permissions + user_group_user_groups_perms = \ + Session().query(UserGroupUserGroupToPerm, Permission, UserGroup)\ + .join((UserGroup, UserGroupUserGroupToPerm.target_user_group_id + == UserGroup.users_group_id))\ + .join((Permission, UserGroupUserGroupToPerm.permission_id + == Permission.permission_id))\ + .join((UserGroupMember, UserGroupUserGroupToPerm.user_group_id + == UserGroupMember.users_group_id))\ + .filter(UserGroupMember.user_id == uid)\ + .all() + + multiple_counter = collections.defaultdict(int) + for perm in user_group_user_groups_perms: + g_k = perm.UserGroupUserGroupToPerm.target_user_group.users_group_name + multiple_counter[g_k] += 1 + p = perm.Permission.permission_name + cur_perm = permissions[UK][g_k] + if multiple_counter[g_k] > 1: + p = _choose_perm(p, cur_perm) + permissions[UK][g_k] = p + + #user explicit permission for user groups + user_user_groups_perms = Permission.get_default_user_group_perms(uid) + for perm in user_user_groups_perms: + u_k = perm.UserUserGroupToPerm.user_group.users_group_name + p = perm.Permission.permission_name + cur_perm = permissions[UK][u_k] + if not explicit: + p = _choose_perm(p, cur_perm) + permissions[UK][u_k] = p + + return permissions + + +def allowed_api_access(controller_name, whitelist=None, api_key=None): """ - A simple object that handles all attributes of user in RhodeCode + Check if given controller_name is in whitelist API access + """ + if not whitelist: + from kallithea import CONFIG + whitelist = aslist(CONFIG.get('api_access_controllers_whitelist'), + sep=',') + log.debug('whitelist of API access is: %s' % (whitelist)) + api_access_valid = controller_name in whitelist + if api_access_valid: + log.debug('controller:%s is in API whitelist' % (controller_name)) + else: + msg = 'controller: %s is *NOT* in API whitelist' % (controller_name) + if api_key: + #if we use API key and don't have access it's a warning + log.warning(msg) + else: + log.debug(msg) + return api_access_valid + + +class AuthUser(object): + """ + A simple object that handles all attributes of user in Kallithea It does lookup based on API key,given user, or user present in session Then it fills all required information for such user. It also checks if - anonymous access is enabled and if so, it returns default user as logged - in + anonymous access is enabled and if so, it returns default user as logged in """ def __init__(self, user_id=None, api_key=None, username=None, ip_addr=None): self.user_id = user_id + self._api_key = api_key + self.api_key = None self.username = username self.ip_addr = ip_addr - self.name = '' self.lastname = '' self.email = '' self.is_authenticated = False self.admin = False self.inherit_default_permissions = False - self.permissions = {} - self._api_key = api_key + self.propagate_data() self._instance = None + @LazyProperty + def permissions(self): + return self.get_perms(user=self, cache=False) + + @property + def api_keys(self): + return self.get_api_keys() + def propagate_data(self): user_model = UserModel() - self.anonymous_user = User.get_by_username('default', cache=True) + self.anonymous_user = User.get_default_user(cache=True) is_user_loaded = False - # try go get user by api key - if self._api_key and self._api_key != self.anonymous_user.api_key: - log.debug('Auth User lookup by API KEY %s' % self._api_key) - is_user_loaded = user_model.fill_data(self, api_key=self._api_key) # lookup by userid - elif (self.user_id is not None and - self.user_id != self.anonymous_user.user_id): + if self.user_id is not None and self.user_id != self.anonymous_user.user_id: log.debug('Auth User lookup by USER ID %s' % self.user_id) is_user_loaded = user_model.fill_data(self, user_id=self.user_id) + + # try go get user by api key + elif self._api_key and self._api_key != self.anonymous_user.api_key: + log.debug('Auth User lookup by API KEY %s' % self._api_key) + is_user_loaded = user_model.fill_data(self, api_key=self._api_key) + # lookup by username - elif self.username and \ - str2bool(config.get('container_auth_enabled', False)): - + elif self.username: log.debug('Auth User lookup by USER NAME %s' % self.username) - dbuser = login_container_auth(self.username) - if dbuser is not None: - log.debug('filling all attributes to object') - for k, v in dbuser.get_dict().items(): - setattr(self, k, v) - self.set_authenticated() - is_user_loaded = True + is_user_loaded = user_model.fill_data(self, username=self.username) else: log.debug('No data in %s that could been used to log in' % self) @@ -396,7 +546,42 @@ class AuthUser(object): self.username = 'None' log.debug('Auth User is now %s' % self) - user_model.fill_perms(self) + + def get_perms(self, user, explicit=True, algo='higherwin', cache=False): + """ + Fills user permission attribute with permissions taken from database + works for permissions given for repositories, and for permissions that + are granted to groups + + :param user: instance of User object from database + :param explicit: In case there are permissions both for user and a group + that user is part of, explicit flag will defiine if user will + explicitly override permissions from group, if it's False it will + make decision based on the algo + :param algo: algorithm to decide what permission should be choose if + it's multiple defined, eg user in two different groups. It also + decides if explicit flag is turned off how to specify the permission + for case when user is in a group + have defined separate permission + """ + user_id = user.user_id + user_is_admin = user.is_admin + user_inherit_default_permissions = user.inherit_default_permissions + + log.debug('Getting PERMISSION tree') + compute = conditional_cache('short_term', 'cache_desc', + condition=cache, func=_cached_perms_data) + return compute(user_id, user_is_admin, + user_inherit_default_permissions, explicit, algo) + + def get_api_keys(self): + api_keys = [self.api_key] + for api_key in UserApiKeys.query()\ + .filter(UserApiKeys.user_id == self.user_id)\ + .filter(or_(UserApiKeys.expires == -1, + UserApiKeys.expires >= time.time())).all(): + api_keys.append(api_key.api_key) + + return api_keys @property def is_admin(self): @@ -434,14 +619,21 @@ class AuthUser(object): :returns: boolean, True if ip is in allowed ip range """ - #check IP - allowed_ips = AuthUser.get_allowed_ips(self.user_id, cache=True) - if check_ip_access(source_ip=self.ip_addr, allowed_ips=allowed_ips): - log.debug('IP:%s is in range of %s' % (self.ip_addr, allowed_ips)) + # check IP + inherit = self.inherit_default_permissions + return AuthUser.check_ip_allowed(self.user_id, self.ip_addr, + inherit_from_default=inherit) + + @classmethod + def check_ip_allowed(cls, user_id, ip_addr, inherit_from_default): + allowed_ips = AuthUser.get_allowed_ips(user_id, cache=True, + inherit_from_default=inherit_from_default) + if check_ip_access(source_ip=ip_addr, allowed_ips=allowed_ips): + log.debug('IP:%s is in range of %s' % (ip_addr, allowed_ips)) return True else: log.info('Access for IP:%s forbidden, ' - 'not in %s' % (self.ip_addr, allowed_ips)) + 'not in %s' % (ip_addr, allowed_ips)) return False def __repr__(self): @@ -471,12 +663,30 @@ class AuthUser(object): return AuthUser(user_id, api_key, username) @classmethod - def get_allowed_ips(cls, user_id, cache=False): + def get_allowed_ips(cls, user_id, cache=False, inherit_from_default=False): _set = set() + + if inherit_from_default: + default_ips = UserIpMap.query().filter(UserIpMap.user == + User.get_default_user(cache=True)) + if cache: + default_ips = default_ips.options(FromCache("sql_cache_short", + "get_user_ips_default")) + + # populate from default user + for ip in default_ips: + try: + _set.add(ip.ip_addr) + except ObjectDeletedError: + # since we use heavy caching sometimes it happens that we get + # deleted objects here, we just skip them + pass + user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id) if cache: user_ips = user_ips.options(FromCache("sql_cache_short", "get_user_ips_%s" % user_id)) + for ip in user_ips: try: _set.add(ip.ip_addr) @@ -528,40 +738,47 @@ class LoginRequired(object): def __wrapper(self, func, *fargs, **fkwargs): cls = fargs[0] - user = cls.rhodecode_user + user = cls.authuser loc = "%s:%s" % (cls.__class__.__name__, func.__name__) - # defined whitelist of controllers which API access will be enabled - whitelist = aslist(config.get('api_access_controllers_whitelist'), - sep=',') - api_access_whitelist = loc in whitelist - log.debug('loc:%s is in API whitelist:%s:%s' % (loc, whitelist, - api_access_whitelist)) - #check IP - ip_access_ok = True + + # check if our IP is allowed + ip_access_valid = True if not user.ip_allowed: - from rhodecode.lib import helpers as h + from kallithea.lib import helpers as h h.flash(h.literal(_('IP %s not allowed' % (user.ip_addr))), category='warning') - ip_access_ok = False + ip_access_valid = False - api_access_ok = False - if self.api_access or api_access_whitelist: + # check if we used an APIKEY and it's a valid one + # defined whitelist of controllers which API access will be enabled + _api_key = request.GET.get('api_key', '') + api_access_valid = allowed_api_access(loc, api_key=_api_key) + + # explicit controller is enabled or API is in our whitelist + if self.api_access or api_access_valid: log.debug('Checking API KEY access for %s' % cls) - if user.api_key == request.GET.get('api_key'): - api_access_ok = True + if _api_key and _api_key in user.api_keys: + api_access_valid = True + log.debug('API KEY ****%s is VALID' % _api_key[-4:]) else: - log.debug("API KEY token not valid") + api_access_valid = False + if not _api_key: + log.debug("API KEY *NOT* present in request") + else: + log.warn("API KEY ****%s *NOT* valid" % _api_key[-4:]) log.debug('Checking if %s is authenticated @ %s' % (user.username, loc)) - if (user.is_authenticated or api_access_ok) and ip_access_ok: - reason = 'RegularAuth' if user.is_authenticated else 'APIAuth' - log.info('user %s is authenticated and granted access to %s ' - 'using %s' % (user.username, loc, reason) + reason = 'RegularAuth' if user.is_authenticated else 'APIAuth' + + if ip_access_valid and (user.is_authenticated or api_access_valid): + log.info('user %s authenticating with:%s IS authenticated on func %s ' + % (user, reason, loc) ) return func(*fargs, **fkwargs) else: - log.warn('user %s NOT authenticated on func: %s' % ( - user, loc) + log.warn('user %s authenticating with:%s NOT authenticated on func: %s: ' + 'IP_ACCESS:%s API_ACCESS:%s' + % (user, reason, loc, ip_access_valid, api_access_valid) ) p = url.current() @@ -579,16 +796,16 @@ class NotAnonymous(object): def __wrapper(self, func, *fargs, **fkwargs): cls = fargs[0] - self.user = cls.rhodecode_user + self.user = cls.authuser log.debug('Checking if user is not anonymous @%s' % cls) - anonymous = self.user.username == 'default' + anonymous = self.user.username == User.DEFAULT_USER if anonymous: p = url.current() - import rhodecode.lib.helpers as h + import kallithea.lib.helpers as h h.flash(_('You need to be a registered user to ' 'perform this action'), category='warning') @@ -601,10 +818,6 @@ class PermsDecorator(object): """Base class for controller decorators""" def __init__(self, *required_perms): - available_perms = config['available_permissions'] - for perm in required_perms: - if perm not in available_perms: - raise Exception("'%s' permission is not defined" % perm) self.required_perms = set(required_perms) self.user_perms = None @@ -613,7 +826,7 @@ class PermsDecorator(object): def __wrapper(self, func, *fargs, **fkwargs): cls = fargs[0] - self.user = cls.rhodecode_user + self.user = cls.authuser self.user_perms = self.user.permissions log.debug('checking %s permissions %s for %s %s', self.__class__.__name__, self.required_perms, cls, self.user) @@ -624,12 +837,12 @@ class PermsDecorator(object): else: log.debug('Permission denied for %s %s' % (cls, self.user)) - anonymous = self.user.username == 'default' + anonymous = self.user.username == User.DEFAULT_USER if anonymous: p = url.current() - import rhodecode.lib.helpers as h + import kallithea.lib.helpers as h h.flash(_('You need to be a signed in to ' 'view this page'), category='warning') @@ -703,14 +916,14 @@ class HasRepoPermissionAnyDecorator(Perm return False -class HasReposGroupPermissionAllDecorator(PermsDecorator): +class HasRepoGroupPermissionAllDecorator(PermsDecorator): """ Checks for access permission for all given predicates for specific repository group. All of them have to be meet in order to fulfill the request """ def check_permissions(self): - group_name = get_repos_group_slug(request) + group_name = get_repo_group_slug(request) try: user_perms = set([self.user_perms['repositories_groups'][group_name]]) except KeyError: @@ -721,14 +934,14 @@ class HasReposGroupPermissionAllDecorato return False -class HasReposGroupPermissionAnyDecorator(PermsDecorator): +class HasRepoGroupPermissionAnyDecorator(PermsDecorator): """ Checks for access permission for any of given predicates for specific repository group. In order to fulfill the request any of predicates must be meet """ def check_permissions(self): - group_name = get_repos_group_slug(request) + group_name = get_repo_group_slug(request) try: user_perms = set([self.user_perms['repositories_groups'][group_name]]) except KeyError: @@ -782,27 +995,28 @@ class PermsFunction(object): """Base function for other check functions""" def __init__(self, *perms): - available_perms = config['available_permissions'] - - for perm in perms: - if perm not in available_perms: - raise Exception("'%s' permission is not defined" % perm) self.required_perms = set(perms) self.user_perms = None self.repo_name = None self.group_name = None - def __call__(self, check_location=''): - #TODO: put user as attribute here - user = request.user + def __call__(self, check_location='', user=None): + if not user: + #TODO: remove this someday,put as user as attribute here + user = request.user + + # init auth user if not already given + if not isinstance(user, AuthUser): + user = AuthUser(user.user_id) + cls_name = self.__class__.__name__ check_scope = { 'HasPermissionAll': '', 'HasPermissionAny': '', 'HasRepoPermissionAll': 'repo:%s' % self.repo_name, 'HasRepoPermissionAny': 'repo:%s' % self.repo_name, - 'HasReposGroupPermissionAll': 'group:%s' % self.group_name, - 'HasReposGroupPermissionAny': 'group:%s' % self.group_name, + 'HasRepoGroupPermissionAll': 'group:%s' % self.group_name, + 'HasRepoGroupPermissionAny': 'group:%s' % self.group_name, }.get(cls_name, '?') log.debug('checking cls:%s %s usr:%s %s @ %s', cls_name, self.required_perms, user, check_scope, @@ -812,13 +1026,15 @@ class PermsFunction(object): return False self.user_perms = user.permissions if self.check_permissions(): - log.debug('Permission to %s granted for user: %s @ %s', self.repo_name, user, - check_location or 'unspecified location') + log.debug('Permission to %s granted for user: %s @ %s' + % (check_scope, user, + check_location or 'unspecified location')) return True else: - log.debug('Permission to %s denied for user: %s @ %s', self.repo_name, user, - check_location or 'unspecified location') + log.debug('Permission to %s denied for user: %s @ %s' + % (check_scope, user, + check_location or 'unspecified location')) return False def check_permissions(self): @@ -841,9 +1057,9 @@ class HasPermissionAny(PermsFunction): class HasRepoPermissionAll(PermsFunction): - def __call__(self, repo_name=None, check_location=''): + def __call__(self, repo_name=None, check_location='', user=None): self.repo_name = repo_name - return super(HasRepoPermissionAll, self).__call__(check_location) + return super(HasRepoPermissionAll, self).__call__(check_location, user) def check_permissions(self): if not self.repo_name: @@ -861,9 +1077,9 @@ class HasRepoPermissionAll(PermsFunction class HasRepoPermissionAny(PermsFunction): - def __call__(self, repo_name=None, check_location=''): + def __call__(self, repo_name=None, check_location='', user=None): self.repo_name = repo_name - return super(HasRepoPermissionAny, self).__call__(check_location) + return super(HasRepoPermissionAny, self).__call__(check_location, user) def check_permissions(self): if not self.repo_name: @@ -880,10 +1096,10 @@ class HasRepoPermissionAny(PermsFunction return False -class HasReposGroupPermissionAny(PermsFunction): - def __call__(self, group_name=None, check_location=''): +class HasRepoGroupPermissionAny(PermsFunction): + def __call__(self, group_name=None, check_location='', user=None): self.group_name = group_name - return super(HasReposGroupPermissionAny, self).__call__(check_location) + return super(HasRepoGroupPermissionAny, self).__call__(check_location, user) def check_permissions(self): try: @@ -897,10 +1113,10 @@ class HasReposGroupPermissionAny(PermsFu return False -class HasReposGroupPermissionAll(PermsFunction): - def __call__(self, group_name=None, check_location=''): +class HasRepoGroupPermissionAll(PermsFunction): + def __call__(self, group_name=None, check_location='', user=None): self.group_name = group_name - return super(HasReposGroupPermissionAll, self).__call__(check_location) + return super(HasRepoGroupPermissionAll, self).__call__(check_location, user) def check_permissions(self): try: @@ -915,9 +1131,9 @@ class HasReposGroupPermissionAll(PermsFu class HasUserGroupPermissionAny(PermsFunction): - def __call__(self, user_group_name=None, check_location=''): + def __call__(self, user_group_name=None, check_location='', user=None): self.user_group_name = user_group_name - return super(HasUserGroupPermissionAny, self).__call__(check_location) + return super(HasUserGroupPermissionAny, self).__call__(check_location, user) def check_permissions(self): try: @@ -932,9 +1148,9 @@ class HasUserGroupPermissionAny(PermsFun class HasUserGroupPermissionAll(PermsFunction): - def __call__(self, user_group_name=None, check_location=''): + def __call__(self, user_group_name=None, check_location='', user=None): self.user_group_name = user_group_name - return super(HasUserGroupPermissionAll, self).__call__(check_location) + return super(HasUserGroupPermissionAll, self).__call__(check_location, user) def check_permissions(self): try: @@ -947,6 +1163,7 @@ class HasUserGroupPermissionAll(PermsFun return True return False + #============================================================================== # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH #============================================================================== @@ -974,15 +1191,11 @@ class HasPermissionAnyMiddleware(object) 'permissions %s for user:%s repository:%s', self.user_perms, self.username, self.repo_name) if self.required_perms.intersection(self.user_perms): - log.debug('permission granted for user:%s on repo:%s' % ( - self.username, self.repo_name - ) - ) + log.debug('Permission to repo: %s granted for user: %s @ %s' + % (self.repo_name, self.username, 'PermissionMiddleware')) return True - log.debug('permission denied for user:%s on repo:%s' % ( - self.username, self.repo_name - ) - ) + log.debug('Permission to repo: %s denied for user: %s @ %s' + % (self.repo_name, self.username, 'PermissionMiddleware')) return False @@ -993,11 +1206,18 @@ class _BaseApiPerm(object): def __init__(self, *perms): self.required_perms = set(perms) - def __call__(self, check_location='unspecified', user=None, repo_name=None): + def __call__(self, check_location=None, user=None, repo_name=None, + group_name=None): cls_name = self.__class__.__name__ - check_scope = 'user:%s, repo:%s' % (user, repo_name) - log.debug('checking cls:%s %s %s @ %s', cls_name, - self.required_perms, check_scope, check_location) + check_scope = 'user:%s' % (user) + if repo_name: + check_scope += ', repo:%s' % (repo_name) + + if group_name: + check_scope += ', repo group:%s' % (group_name) + + log.debug('checking cls:%s %s %s @ %s' + % (cls_name, self.required_perms, check_scope, check_location)) if not user: log.debug('Empty User passed into arguments') return False @@ -1005,18 +1225,19 @@ class _BaseApiPerm(object): ## process user if not isinstance(user, AuthUser): user = AuthUser(user.user_id) - - if self.check_permissions(user.permissions, repo_name): - log.debug('Permission to %s granted for user: %s @ %s', repo_name, - user, check_location) + if not check_location: + check_location = 'unspecified' + if self.check_permissions(user.permissions, repo_name, group_name): + log.debug('Permission to %s granted for user: %s @ %s' + % (check_scope, user, check_location)) return True else: - log.debug('Permission to %s denied for user: %s @ %s', repo_name, - user, check_location) + log.debug('Permission to %s denied for user: %s @ %s' + % (check_scope, user, check_location)) return False - def check_permissions(self, perm_defs, repo_name): + def check_permissions(self, perm_defs, repo_name=None, group_name=None): """ implement in child class should return True if permissions are ok, False otherwise @@ -1028,59 +1249,35 @@ class _BaseApiPerm(object): class HasPermissionAllApi(_BaseApiPerm): - def __call__(self, user, check_location=''): - return super(HasPermissionAllApi, self)\ - .__call__(check_location=check_location, user=user) - - def check_permissions(self, perm_defs, repo): + def check_permissions(self, perm_defs, repo_name=None, group_name=None): if self.required_perms.issubset(perm_defs.get('global')): return True return False class HasPermissionAnyApi(_BaseApiPerm): - def __call__(self, user, check_location=''): - return super(HasPermissionAnyApi, self)\ - .__call__(check_location=check_location, user=user) - - def check_permissions(self, perm_defs, repo): + def check_permissions(self, perm_defs, repo_name=None, group_name=None): if self.required_perms.intersection(perm_defs.get('global')): return True return False class HasRepoPermissionAllApi(_BaseApiPerm): - def __call__(self, user, repo_name, check_location=''): - return super(HasRepoPermissionAllApi, self)\ - .__call__(check_location=check_location, user=user, - repo_name=repo_name) - - def check_permissions(self, perm_defs, repo_name): - + def check_permissions(self, perm_defs, repo_name=None, group_name=None): try: - self._user_perms = set( - [perm_defs['repositories'][repo_name]] - ) + _user_perms = set([perm_defs['repositories'][repo_name]]) except KeyError: log.warning(traceback.format_exc()) return False - if self.required_perms.issubset(self._user_perms): + if self.required_perms.issubset(_user_perms): return True return False class HasRepoPermissionAnyApi(_BaseApiPerm): - def __call__(self, user, repo_name, check_location=''): - return super(HasRepoPermissionAnyApi, self)\ - .__call__(check_location=check_location, user=user, - repo_name=repo_name) - - def check_permissions(self, perm_defs, repo_name): - + def check_permissions(self, perm_defs, repo_name=None, group_name=None): try: - _user_perms = set( - [perm_defs['repositories'][repo_name]] - ) + _user_perms = set([perm_defs['repositories'][repo_name]]) except KeyError: log.warning(traceback.format_exc()) return False @@ -1089,6 +1286,28 @@ class HasRepoPermissionAnyApi(_BaseApiPe return False +class HasRepoGroupPermissionAnyApi(_BaseApiPerm): + def check_permissions(self, perm_defs, repo_name=None, group_name=None): + try: + _user_perms = set([perm_defs['repositories_groups'][group_name]]) + except KeyError: + log.warning(traceback.format_exc()) + return False + if self.required_perms.intersection(_user_perms): + return True + return False + +class HasRepoGroupPermissionAllApi(_BaseApiPerm): + def check_permissions(self, perm_defs, repo_name=None, group_name=None): + try: + _user_perms = set([perm_defs['repositories_groups'][group_name]]) + except KeyError: + log.warning(traceback.format_exc()) + return False + if self.required_perms.issubset(_user_perms): + return True + return False + def check_ip_access(source_ip, allowed_ips=None): """ Checks if source_ip is a subnet of any of allowed_ips. @@ -1096,12 +1315,14 @@ def check_ip_access(source_ip, allowed_i :param source_ip: :param allowed_ips: list of allowed ips together with mask """ - from rhodecode.lib import ipaddr + from kallithea.lib import ipaddr log.debug('checking if ip:%s is subnet of %s' % (source_ip, allowed_ips)) if isinstance(allowed_ips, (tuple, list, set)): for ip in allowed_ips: try: if ipaddr.IPAddress(source_ip) in ipaddr.IPNetwork(ip): + log.debug('IP %s is network %s' % + (ipaddr.IPAddress(source_ip), ipaddr.IPNetwork(ip))) return True # for any case we cannot determine the IP, don't crash just # skip it and log as error, we want to say forbidden still when diff --git a/kallithea/lib/auth_modules/__init__.py b/kallithea/lib/auth_modules/__init__.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/auth_modules/__init__.py @@ -0,0 +1,422 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +Authentication modules +""" + +import logging +import traceback + +from kallithea import EXTERN_TYPE_INTERNAL +from kallithea.lib.compat import importlib +from kallithea.lib.utils2 import str2bool +from kallithea.lib.compat import formatted_json, hybrid_property +from kallithea.lib.auth import PasswordGenerator +from kallithea.model.user import UserModel +from kallithea.model.db import Setting, User, UserGroup +from kallithea.model.meta import Session +from kallithea.model.user_group import UserGroupModel + +log = logging.getLogger(__name__) + + +class LazyFormencode(object): + def __init__(self, formencode_obj, *args, **kwargs): + self.formencode_obj = formencode_obj + self.args = args + self.kwargs = kwargs + + def __call__(self, *args, **kwargs): + from inspect import isfunction + formencode_obj = self.formencode_obj + if isfunction(formencode_obj): + #case we wrap validators into functions + formencode_obj = self.formencode_obj(*args, **kwargs) + return formencode_obj(*self.args, **self.kwargs) + + +class KallitheaAuthPluginBase(object): + auth_func_attrs = { + "username": "unique username", + "firstname": "first name", + "lastname": "last name", + "email": "email address", + "groups": '["list", "of", "groups"]', + "extern_name": "name in external source of record", + "extern_type": "type of external source of record", + "admin": 'True|False defines if user should be Kallithea super admin', + "active": 'True|False defines active state of user internally for Kallithea', + "active_from_extern": "True|False\None, active state from the external auth, " + "None means use definition from Kallithea extern_type active value" + } + + @property + def validators(self): + """ + Exposes Kallithea validators modules + """ + # this is a hack to overcome issues with pylons threadlocals and + # translator object _() not beein registered properly. + class LazyCaller(object): + def __init__(self, name): + self.validator_name = name + + def __call__(self, *args, **kwargs): + from kallithea.model import validators as v + obj = getattr(v, self.validator_name) + #log.debug('Initializing lazy formencode object: %s' % obj) + return LazyFormencode(obj, *args, **kwargs) + + + class ProxyGet(object): + def __getattribute__(self, name): + return LazyCaller(name) + + return ProxyGet() + + @hybrid_property + def name(self): + """ + Returns the name of this authentication plugin. + + :returns: string + """ + raise NotImplementedError("Not implemented in base class") + + @hybrid_property + def is_container_auth(self): + """ + Returns bool if this module uses container auth. + + This property will trigger an automatic call to authenticate on + a visit to the website or during a push/pull. + + :returns: bool + """ + return False + + def accepts(self, user, accepts_empty=True): + """ + Checks if this authentication module should accept a request for + the current user. + + :param user: user object fetched using plugin's get_user() method. + :param accepts_empty: if True accepts don't allow the user to be empty + :returns: boolean + """ + plugin_name = self.name + if not user and not accepts_empty: + log.debug('User is empty not allowed to authenticate') + return False + + if user and user.extern_type and user.extern_type != plugin_name: + log.debug('User %s should authenticate using %s this is %s, skipping' + % (user, user.extern_type, plugin_name)) + + return False + return True + + def get_user(self, username=None, **kwargs): + """ + Helper method for user fetching in plugins, by default it's using + simple fetch by username, but this method can be custimized in plugins + eg. container auth plugin to fetch user by environ params + + :param username: username if given to fetch from database + :param kwargs: extra arguments needed for user fetching. + """ + user = None + log.debug('Trying to fetch user `%s` from Kallithea database' + % (username)) + if username: + user = User.get_by_username(username) + if not user: + log.debug('Fallback to fetch user in case insensitive mode') + user = User.get_by_username(username, case_insensitive=True) + else: + log.debug('provided username:`%s` is empty skipping...' % username) + return user + + def settings(self): + """ + Return a list of the form: + [ + { + "name": "OPTION_NAME", + "type": "[bool|password|string|int|select]", + ["values": ["opt1", "opt2", ...]] + "validator": "expr" + "description": "A short description of the option" [, + "default": Default Value], + ["formname": "Friendly Name for Forms"] + } [, ...] + ] + + This is used to interrogate the authentication plugin as to what + settings it expects to be present and configured. + + 'type' is a shorthand notation for what kind of value this option is. + This is primarily used by the auth web form to control how the option + is configured. + bool : checkbox + password : password input box + string : input box + select : single select dropdown + + 'validator' is an lazy instantiated form field validator object, ala + formencode. You need to *call* this object to init the validators. + All calls to Kallithea validators should be used through self.validators + which is a lazy loading proxy of formencode module. + """ + raise NotImplementedError("Not implemented in base class") + + def plugin_settings(self): + """ + This method is called by the authentication framework, not the .settings() + method. This method adds a few default settings (e.g., "active"), so that + plugin authors don't have to maintain a bunch of boilerplate. + + OVERRIDING THIS METHOD WILL CAUSE YOUR PLUGIN TO FAIL. + """ + + rcsettings = self.settings() + rcsettings.insert(0, { + "name": "enabled", + "validator": self.validators.StringBoolean(if_missing=False), + "type": "bool", + "description": "Enable or Disable this Authentication Plugin", + "formname": "Enabled" + } + ) + return rcsettings + + def user_activation_state(self): + """ + Defines user activation state when creating new users + + :returns: boolean + """ + raise NotImplementedError("Not implemented in base class") + + def auth(self, userobj, username, passwd, settings, **kwargs): + """ + Given a user object (which may be null), username, a plaintext password, + and a settings object (containing all the keys needed as listed in settings()), + authenticate this user's login attempt. + + Return None on failure. On success, return a dictionary of the form: + + see: KallitheaAuthPluginBase.auth_func_attrs + This is later validated for correctness + """ + raise NotImplementedError("not implemented in base class") + + def _authenticate(self, userobj, username, passwd, settings, **kwargs): + """ + Wrapper to call self.auth() that validates call on it + + :param userobj: userobj + :param username: username + :param passwd: plaintext password + :param settings: plugin settings + """ + auth = self.auth(userobj, username, passwd, settings, **kwargs) + if auth: + return self._validate_auth_return(auth) + return auth + + def _validate_auth_return(self, ret): + if not isinstance(ret, dict): + raise Exception('returned value from auth must be a dict') + for k in self.auth_func_attrs: + if k not in ret: + raise Exception('Missing %s attribute from returned data' % k) + return ret + + +class KallitheaExternalAuthPlugin(KallitheaAuthPluginBase): + def use_fake_password(self): + """ + Return a boolean that indicates whether or not we should set the user's + password to a random value when it is authenticated by this plugin. + If your plugin provides authentication, then you will generally want this. + + :returns: boolean + """ + raise NotImplementedError("Not implemented in base class") + + def _authenticate(self, userobj, username, passwd, settings, **kwargs): + auth = super(KallitheaExternalAuthPlugin, self)._authenticate( + userobj, username, passwd, settings, **kwargs) + if auth: + # maybe plugin will clean the username ? + # we should use the return value + username = auth['username'] + # if user is not active from our extern type we should fail to authe + # this can prevent from creating users in Kallithea when using + # external authentication, but if it's inactive user we shouldn't + # create that user anyway + if auth['active_from_extern'] is False: + log.warning("User %s authenticated against %s, but is inactive" + % (username, self.__module__)) + return None + + if self.use_fake_password(): + # Randomize the PW because we don't need it, but don't want + # them blank either + passwd = PasswordGenerator().gen_password(length=8) + + log.debug('Updating or creating user info from %s plugin' + % self.name) + user = UserModel().create_or_update( + username=username, + password=passwd, + email=auth["email"], + firstname=auth["firstname"], + lastname=auth["lastname"], + active=auth["active"], + admin=auth["admin"], + extern_name=auth["extern_name"], + extern_type=self.name + ) + Session().flush() + # enforce user is just in given groups, all of them has to be ones + # created from plugins. We store this info in _group_data JSON field + try: + groups = auth['groups'] or [] + UserGroupModel().enforce_groups(user, groups, self.name) + except Exception: + # for any reason group syncing fails, we should proceed with login + log.error(traceback.format_exc()) + Session().commit() + return auth + + +def importplugin(plugin): + """ + Imports and returns the authentication plugin in the module named by plugin + (e.g., plugin='kallithea.lib.auth_modules.auth_internal'). Returns the + KallitheaAuthPluginBase subclass on success, raises exceptions on failure. + + raises: + AttributeError -- no KallitheaAuthPlugin class in the module + TypeError -- if the KallitheaAuthPlugin is not a subclass of ours KallitheaAuthPluginBase + ImportError -- if we couldn't import the plugin at all + """ + log.debug("Importing %s" % plugin) + if not plugin.startswith(u'kallithea.lib.auth_modules.auth_'): + parts = plugin.split(u'.lib.auth_modules.auth_', 1) + if len(parts) == 2: + _module, pn = parts + if pn == EXTERN_TYPE_INTERNAL: + pn = "internal" + plugin = u'kallithea.lib.auth_modules.auth_' + pn + PLUGIN_CLASS_NAME = "KallitheaAuthPlugin" + try: + module = importlib.import_module(plugin) + except (ImportError, TypeError): + log.error(traceback.format_exc()) + # TODO: make this more error prone, if by some accident we screw up + # the plugin name, the crash is preatty bad and hard to recover + raise + + log.debug("Loaded auth plugin from %s (module:%s, file:%s)" + % (plugin, module.__name__, module.__file__)) + + pluginclass = getattr(module, PLUGIN_CLASS_NAME) + if not issubclass(pluginclass, KallitheaAuthPluginBase): + raise TypeError("Authentication class %s.KallitheaAuthPlugin is not " + "a subclass of %s" % (plugin, KallitheaAuthPluginBase)) + return pluginclass + + +def loadplugin(plugin): + """ + Loads and returns an instantiated authentication plugin. + + see: importplugin + """ + plugin = importplugin(plugin)() + if plugin.plugin_settings.im_func != KallitheaAuthPluginBase.plugin_settings.im_func: + raise TypeError("Authentication class %s.KallitheaAuthPluginBase " + "has overriden the plugin_settings method, which is " + "forbidden." % plugin) + return plugin + + +def authenticate(username, password, environ=None): + """ + Authentication function used for access control, + It tries to authenticate based on enabled authentication modules. + + :param username: username can be empty for container auth + :param password: password can be empty for container auth + :param environ: environ headers passed for container auth + :returns: None if auth failed, plugin_user dict if auth is correct + """ + + auth_plugins = Setting.get_auth_plugins() + log.debug('Authentication against %s plugins' % (auth_plugins,)) + for module in auth_plugins: + try: + plugin = loadplugin(module) + except (ImportError, AttributeError, TypeError), e: + raise ImportError('Failed to load authentication module %s : %s' + % (module, str(e))) + log.debug('Trying authentication using ** %s **' % (module,)) + # load plugin settings from Kallithea database + plugin_name = plugin.name + plugin_settings = {} + for v in plugin.plugin_settings(): + conf_key = "auth_%s_%s" % (plugin_name, v["name"]) + setting = Setting.get_by_name(conf_key) + plugin_settings[v["name"]] = setting.app_settings_value if setting else None + log.debug('Plugin settings \n%s' % formatted_json(plugin_settings)) + + if not str2bool(plugin_settings["enabled"]): + log.info("Authentication plugin %s is disabled, skipping for %s" + % (module, username)) + continue + + # use plugin's method of user extraction. + user = plugin.get_user(username, environ=environ, + settings=plugin_settings) + log.debug('Plugin %s extracted user is `%s`' % (module, user)) + if not plugin.accepts(user): + log.debug('Plugin %s does not accept user `%s` for authentication' + % (module, user)) + continue + else: + log.debug('Plugin %s accepted user `%s` for authentication' + % (module, user)) + + log.info('Authenticating user using %s plugin' % plugin.__module__) + # _authenticate is a wrapper for .auth() method of plugin. + # it checks if .auth() sends proper data. for KallitheaExternalAuthPlugin + # it also maps users to Database and maps the attributes returned + # from .auth() to Kallithea database. If this function returns data + # then auth is correct. + plugin_user = plugin._authenticate(user, username, password, + plugin_settings, + environ=environ or {}) + log.debug('PLUGIN USER DATA: %s' % plugin_user) + + if plugin_user: + log.debug('Plugin returned proper authentication data') + return plugin_user + + # we failed to Auth because .auth() method didn't return proper the user + log.warning("User `%s` failed to authenticate against %s" + % (username, plugin.__module__)) + return None diff --git a/kallithea/lib/auth_modules/auth_container.py b/kallithea/lib/auth_modules/auth_container.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/auth_modules/auth_container.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.lib.auth_modules.auth_container +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Kallithea container based authentication plugin + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Created on Nov 17, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import logging +from kallithea.lib import auth_modules +from kallithea.lib.utils2 import str2bool, safe_unicode +from kallithea.lib.compat import hybrid_property +from kallithea.model.db import User + +log = logging.getLogger(__name__) + + +class KallitheaAuthPlugin(auth_modules.KallitheaExternalAuthPlugin): + def __init__(self): + pass + + @hybrid_property + def name(self): + return "container" + + @hybrid_property + def is_container_auth(self): + return True + + def settings(self): + + settings = [ + { + "name": "header", + "validator": self.validators.UnicodeString(strip=True, not_empty=True), + "type": "string", + "description": "Header to extract the user from", + "default": "REMOTE_USER", + "formname": "Header" + }, + { + "name": "fallback_header", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "Header to extract the user from when main one fails", + "default": "HTTP_X_FORWARDED_USER", + "formname": "Fallback header" + }, + { + "name": "clean_username", + "validator": self.validators.StringBoolean(if_missing=False), + "type": "bool", + "description": "Perform cleaning of user, if passed user has @ in username " + "then first part before @ is taken. " + "If there's \\ in the username only the part after \\ is taken", + "default": "True", + "formname": "Clean username" + }, + ] + return settings + + def use_fake_password(self): + return True + + def user_activation_state(self): + def_user_perms = User.get_default_user().AuthUser.permissions['global'] + return 'hg.extern_activate.auto' in def_user_perms + + def _clean_username(self, username): + # Removing realm and domain from username + username = username.partition('@')[0] + username = username.rpartition('\\')[2] + return username + + def _get_username(self, environ, settings): + username = None + environ = environ or {} + if not environ: + log.debug('got empty environ: %s' % environ) + + settings = settings or {} + if settings.get('header'): + header = settings.get('header') + username = environ.get(header) + log.debug('extracted %s:%s' % (header, username)) + + # fallback mode + if not username and settings.get('fallback_header'): + header = settings.get('fallback_header') + username = environ.get(header) + log.debug('extracted %s:%s' % (header, username)) + + if username and str2bool(settings.get('clean_username')): + log.debug('Received username %s from container' % username) + username = self._clean_username(username) + log.debug('New cleanup user is: %s' % username) + return username + + def get_user(self, username=None, **kwargs): + """ + Helper method for user fetching in plugins, by default it's using + simple fetch by username, but this method can be custimized in plugins + eg. container auth plugin to fetch user by environ params + :param username: username if given to fetch + :param kwargs: extra arguments needed for user fetching. + """ + environ = kwargs.get('environ') or {} + settings = kwargs.get('settings') or {} + username = self._get_username(environ, settings) + # we got the username, so use default method now + return super(KallitheaAuthPlugin, self).get_user(username) + + def auth(self, userobj, username, password, settings, **kwargs): + """ + Get's the container_auth username (or email). It tries to get username + from REMOTE_USER if this plugin is enabled, if that fails + it tries to get username from HTTP_X_FORWARDED_USER if fallback header + is set. clean_username extracts the username from this data if it's + having @ in it. + Return None on failure. On success, return a dictionary of the form: + + see: KallitheaAuthPluginBase.auth_func_attrs + + :param userobj: + :param username: + :param password: + :param settings: + :param kwargs: + """ + environ = kwargs.get('environ') + if not environ: + log.debug('Empty environ data skipping...') + return None + + if not userobj: + userobj = self.get_user('', environ=environ, settings=settings) + + # we don't care passed username/password for container auth plugins. + # only way to log in is using environ + username = None + if userobj: + username = getattr(userobj, 'username') + + if not username: + # we don't have any objects in DB user doesn't exist extrac username + # from environ based on the settings + username = self._get_username(environ, settings) + + # if cannot fetch username, it's a no-go for this plugin to proceed + if not username: + return None + + # old attrs fetched from Kallithea database + admin = getattr(userobj, 'admin', False) + active = getattr(userobj, 'active', True) + email = getattr(userobj, 'email', '') + firstname = getattr(userobj, 'firstname', '') + lastname = getattr(userobj, 'lastname', '') + extern_type = getattr(userobj, 'extern_type', '') + + user_attrs = { + 'username': username, + 'firstname': safe_unicode(firstname or username), + 'lastname': safe_unicode(lastname or ''), + 'groups': [], + 'email': email or '', + 'admin': admin or False, + 'active': active, + 'active_from_extern': True, + 'extern_name': username, + 'extern_type': extern_type, + } + + log.info('user `%s` authenticated correctly' % user_attrs['username']) + return user_attrs diff --git a/kallithea/lib/auth_modules/auth_crowd.py b/kallithea/lib/auth_modules/auth_crowd.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/auth_modules/auth_crowd.py @@ -0,0 +1,244 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.lib.auth_modules.auth_crowd +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Kallithea authentication plugin for Atlassian CROWD + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Created on Nov 17, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + + +import base64 +import logging +import urllib2 +from kallithea.lib import auth_modules +from kallithea.lib.compat import json, formatted_json, hybrid_property +from kallithea.model.db import User + +log = logging.getLogger(__name__) + + +class CrowdServer(object): + def __init__(self, *args, **kwargs): + """ + Create a new CrowdServer object that points to IP/Address 'host', + on the given port, and using the given method (https/http). user and + passwd can be set here or with set_credentials. If unspecified, + "version" defaults to "latest". + + example:: + + cserver = CrowdServer(host="127.0.0.1", + port="8095", + user="some_app", + passwd="some_passwd", + version="1") + """ + if not "port" in kwargs: + kwargs["port"] = "8095" + self._logger = kwargs.get("logger", logging.getLogger(__name__)) + self._uri = "%s://%s:%s/crowd" % (kwargs.get("method", "http"), + kwargs.get("host", "127.0.0.1"), + kwargs.get("port", "8095")) + self.set_credentials(kwargs.get("user", ""), + kwargs.get("passwd", "")) + self._version = kwargs.get("version", "latest") + self._url_list = None + self._appname = "crowd" + + def set_credentials(self, user, passwd): + self.user = user + self.passwd = passwd + self._make_opener() + + def _make_opener(self): + mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() + mgr.add_password(None, self._uri, self.user, self.passwd) + handler = urllib2.HTTPBasicAuthHandler(mgr) + self.opener = urllib2.build_opener(handler) + + def _request(self, url, body=None, headers=None, + method=None, noformat=False, + empty_response_ok=False): + _headers = {"Content-type": "application/json", + "Accept": "application/json"} + if self.user and self.passwd: + authstring = base64.b64encode("%s:%s" % (self.user, self.passwd)) + _headers["Authorization"] = "Basic %s" % authstring + if headers: + _headers.update(headers) + log.debug("Sent crowd: \n%s" + % (formatted_json({"url": url, "body": body, + "headers": _headers}))) + request = urllib2.Request(url, body, _headers) + if method: + request.get_method = lambda: method + + global msg + msg = "" + try: + rdoc = self.opener.open(request) + msg = "".join(rdoc.readlines()) + if not msg and empty_response_ok: + rval = {} + rval["status"] = True + rval["error"] = "Response body was empty" + elif not noformat: + rval = json.loads(msg) + rval["status"] = True + else: + rval = "".join(rdoc.readlines()) + except Exception, e: + if not noformat: + rval = {"status": False, + "body": body, + "error": str(e) + "\n" + msg} + else: + rval = None + return rval + + def user_auth(self, username, password): + """Authenticate a user against crowd. Returns brief information about + the user.""" + url = ("%s/rest/usermanagement/%s/authentication?username=%s" + % (self._uri, self._version, username)) + body = json.dumps({"value": password}) + return self._request(url, body) + + def user_groups(self, username): + """Retrieve a list of groups to which this user belongs.""" + url = ("%s/rest/usermanagement/%s/user/group/nested?username=%s" + % (self._uri, self._version, username)) + return self._request(url) + + +class KallitheaAuthPlugin(auth_modules.KallitheaExternalAuthPlugin): + + @hybrid_property + def name(self): + return "crowd" + + def settings(self): + settings = [ + { + "name": "host", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "The FQDN or IP of the Atlassian CROWD Server", + "default": "127.0.0.1", + "formname": "Host" + }, + { + "name": "port", + "validator": self.validators.Number(strip=True), + "type": "int", + "description": "The Port in use by the Atlassian CROWD Server", + "default": 8095, + "formname": "Port" + }, + { + "name": "app_name", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "The Application Name to authenticate to CROWD", + "default": "", + "formname": "Application Name" + }, + { + "name": "app_password", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "The password to authenticate to CROWD", + "default": "", + "formname": "Application Password" + }, + { + "name": "admin_groups", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "A comma separated list of group names that identify users as Kallithea Administrators", + "formname": "Admin Groups" + } + ] + return settings + + def use_fake_password(self): + return True + + def user_activation_state(self): + def_user_perms = User.get_default_user().AuthUser.permissions['global'] + return 'hg.extern_activate.auto' in def_user_perms + + def auth(self, userobj, username, password, settings, **kwargs): + """ + Given a user object (which may be null), username, a plaintext password, + and a settings object (containing all the keys needed as listed in settings()), + authenticate this user's login attempt. + + Return None on failure. On success, return a dictionary of the form: + + see: KallitheaAuthPluginBase.auth_func_attrs + This is later validated for correctness + """ + if not username or not password: + log.debug('Empty username or password skipping...') + return None + + log.debug("Crowd settings: \n%s" % (formatted_json(settings))) + server = CrowdServer(**settings) + server.set_credentials(settings["app_name"], settings["app_password"]) + crowd_user = server.user_auth(username, password) + log.debug("Crowd returned: \n%s" % (formatted_json(crowd_user))) + if not crowd_user["status"]: + return None + + res = server.user_groups(crowd_user["name"]) + log.debug("Crowd groups: \n%s" % (formatted_json(res))) + crowd_user["groups"] = [x["name"] for x in res["groups"]] + + # old attrs fetched from Kallithea database + admin = getattr(userobj, 'admin', False) + active = getattr(userobj, 'active', True) + email = getattr(userobj, 'email', '') + firstname = getattr(userobj, 'firstname', '') + lastname = getattr(userobj, 'lastname', '') + extern_type = getattr(userobj, 'extern_type', '') + + user_attrs = { + 'username': username, + 'firstname': crowd_user["first-name"] or firstname, + 'lastname': crowd_user["last-name"] or lastname, + 'groups': crowd_user["groups"], + 'email': crowd_user["email"] or email, + 'admin': admin, + 'active': active, + 'active_from_extern': crowd_user.get('active'), + 'extern_name': crowd_user["name"], + 'extern_type': extern_type, + } + + # set an admin if we're in admin_groups of crowd + for group in settings["admin_groups"]: + if group in user_attrs["groups"]: + user_attrs["admin"] = True + log.debug("Final crowd user object: \n%s" % (formatted_json(user_attrs))) + log.info('user %s authenticated correctly' % user_attrs['username']) + return user_attrs diff --git a/kallithea/lib/auth_modules/auth_internal.py b/kallithea/lib/auth_modules/auth_internal.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/auth_modules/auth_internal.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.lib.auth_modules.auth_internal +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Kallithea authentication plugin for built in internal auth + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Created on Nov 17, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + + +import logging + +from kallithea import EXTERN_TYPE_INTERNAL +from kallithea.lib import auth_modules +from kallithea.lib.compat import formatted_json, hybrid_property +from kallithea.model.db import User + +log = logging.getLogger(__name__) + + +class KallitheaAuthPlugin(auth_modules.KallitheaAuthPluginBase): + def __init__(self): + pass + + @hybrid_property + def name(self): + return EXTERN_TYPE_INTERNAL + + def settings(self): + return [] + + def user_activation_state(self): + def_user_perms = User.get_default_user().AuthUser.permissions['global'] + return 'hg.register.auto_activate' in def_user_perms + + def accepts(self, user, accepts_empty=True): + """ + Custom accepts for this auth that doesn't accept empty users. We + know that user exisits in database. + """ + return super(KallitheaAuthPlugin, self).accepts(user, + accepts_empty=False) + + def auth(self, userobj, username, password, settings, **kwargs): + if not userobj: + log.debug('userobj was:%s skipping' % (userobj, )) + return None + if userobj.extern_type != self.name: + log.warn("userobj:%s extern_type mismatch got:`%s` expected:`%s`" + % (userobj, userobj.extern_type, self.name)) + return None + + user_attrs = { + "username": userobj.username, + "firstname": userobj.firstname, + "lastname": userobj.lastname, + "groups": [], + "email": userobj.email, + "admin": userobj.admin, + "active": userobj.active, + "active_from_extern": userobj.active, + "extern_name": userobj.user_id, + 'extern_type': userobj.extern_type, + } + + log.debug(formatted_json(user_attrs)) + if userobj.active: + from kallithea.lib import auth + password_match = auth.KallitheaCrypto.hash_check(password, userobj.password) + if userobj.username == User.DEFAULT_USER and userobj.active: + log.info('user %s authenticated correctly as anonymous user' % + username) + return user_attrs + + elif userobj.username == username and password_match: + log.info('user %s authenticated correctly' % user_attrs['username']) + return user_attrs + log.error("user %s had a bad password" % username) + return None + else: + log.warning('user %s tried auth but is disabled' % username) + return None diff --git a/kallithea/lib/auth_modules/auth_ldap.py b/kallithea/lib/auth_modules/auth_ldap.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/auth_modules/auth_ldap.py @@ -0,0 +1,363 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.lib.auth_modules.auth_ldap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Kallithea authentication plugin for LDAP + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Created on Nov 17, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + + +import logging +import traceback + +from kallithea.lib import auth_modules +from kallithea.lib.compat import hybrid_property +from kallithea.lib.utils2 import safe_unicode, safe_str +from kallithea.lib.exceptions import ( + LdapConnectionError, LdapUsernameError, LdapPasswordError, LdapImportError +) +from kallithea.model.db import User + +log = logging.getLogger(__name__) + +try: + import ldap +except ImportError: + # means that python-ldap is not installed + ldap = None + + +class AuthLdap(object): + + def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='', + tls_kind='PLAIN', tls_reqcert='DEMAND', ldap_version=3, + ldap_filter='(&(objectClass=user)(!(objectClass=computer)))', + search_scope='SUBTREE', attr_login='uid'): + if ldap is None: + raise LdapImportError + + self.ldap_version = ldap_version + ldap_server_type = 'ldap' + + self.TLS_KIND = tls_kind + + if self.TLS_KIND == 'LDAPS': + port = port or 689 + ldap_server_type = ldap_server_type + 's' + + OPT_X_TLS_DEMAND = 2 + self.TLS_REQCERT = getattr(ldap, 'OPT_X_TLS_%s' % tls_reqcert, + OPT_X_TLS_DEMAND) + # split server into list + self.LDAP_SERVER_ADDRESS = server.split(',') + self.LDAP_SERVER_PORT = port + + # USE FOR READ ONLY BIND TO LDAP SERVER + self.LDAP_BIND_DN = safe_str(bind_dn) + self.LDAP_BIND_PASS = safe_str(bind_pass) + _LDAP_SERVERS = [] + for host in self.LDAP_SERVER_ADDRESS: + _LDAP_SERVERS.append("%s://%s:%s" % (ldap_server_type, + host.replace(' ', ''), + self.LDAP_SERVER_PORT)) + self.LDAP_SERVER = str(', '.join(s for s in _LDAP_SERVERS)) + self.BASE_DN = safe_str(base_dn) + self.LDAP_FILTER = safe_str(ldap_filter) + self.SEARCH_SCOPE = getattr(ldap, 'SCOPE_%s' % search_scope) + self.attr_login = attr_login + + def authenticate_ldap(self, username, password): + """ + Authenticate a user via LDAP and return his/her LDAP properties. + + Raises AuthenticationError if the credentials are rejected, or + EnvironmentError if the LDAP server can't be reached. + + :param username: username + :param password: password + """ + + from kallithea.lib.helpers import chop_at + + uid = chop_at(username, "@%s" % self.LDAP_SERVER_ADDRESS) + + if not password: + log.debug("Attempt to authenticate LDAP user " + "with blank password rejected.") + raise LdapPasswordError() + if "," in username: + raise LdapUsernameError("invalid character in username: ,") + try: + if hasattr(ldap, 'OPT_X_TLS_CACERTDIR'): + ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, + '/etc/openldap/cacerts') + ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF) + ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON) + ldap.set_option(ldap.OPT_TIMEOUT, 20) + ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 10) + ldap.set_option(ldap.OPT_TIMELIMIT, 15) + if self.TLS_KIND != 'PLAIN': + ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, self.TLS_REQCERT) + server = ldap.initialize(self.LDAP_SERVER) + if self.ldap_version == 2: + server.protocol = ldap.VERSION2 + else: + server.protocol = ldap.VERSION3 + + if self.TLS_KIND == 'START_TLS': + server.start_tls_s() + + if self.LDAP_BIND_DN and self.LDAP_BIND_PASS: + log.debug('Trying simple_bind with password and given DN: %s' + % self.LDAP_BIND_DN) + server.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS) + + filter_ = '(&%s(%s=%s))' % (self.LDAP_FILTER, self.attr_login, + username) + log.debug("Authenticating %r filter %s at %s", self.BASE_DN, + filter_, self.LDAP_SERVER) + lobjects = server.search_ext_s(self.BASE_DN, self.SEARCH_SCOPE, + filter_) + + if not lobjects: + raise ldap.NO_SUCH_OBJECT() + + for (dn, _attrs) in lobjects: + if dn is None: + continue + + try: + log.debug('Trying simple bind with %s' % dn) + server.simple_bind_s(dn, safe_str(password)) + attrs = server.search_ext_s(dn, ldap.SCOPE_BASE, + '(objectClass=*)')[0][1] + break + + except ldap.INVALID_CREDENTIALS: + log.debug("LDAP rejected password for user '%s' (%s): %s" + % (uid, username, dn)) + + else: + log.debug("No matching LDAP objects for authentication " + "of '%s' (%s)", uid, username) + raise LdapPasswordError() + + except ldap.NO_SUCH_OBJECT: + log.debug("LDAP says no such user '%s' (%s)" % (uid, username)) + raise LdapUsernameError() + except ldap.SERVER_DOWN: + raise LdapConnectionError("LDAP can't access authentication server") + + return dn, attrs + + +class KallitheaAuthPlugin(auth_modules.KallitheaExternalAuthPlugin): + def __init__(self): + self._logger = logging.getLogger(__name__) + self._tls_kind_values = ["PLAIN", "LDAPS", "START_TLS"] + self._tls_reqcert_values = ["NEVER", "ALLOW", "TRY", "DEMAND", "HARD"] + self._search_scopes = ["BASE", "ONELEVEL", "SUBTREE"] + + @hybrid_property + def name(self): + return "ldap" + + def settings(self): + settings = [ + { + "name": "host", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "Host of the LDAP Server", + "formname": "LDAP Host" + }, + { + "name": "port", + "validator": self.validators.Number(strip=True, not_empty=True), + "type": "string", + "description": "Port that the LDAP server is listening on", + "default": 389, + "formname": "Port" + }, + { + "name": "dn_user", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "User to connect to LDAP", + "formname": "Account" + }, + { + "name": "dn_pass", + "validator": self.validators.UnicodeString(strip=True), + "type": "password", + "description": "Password to connect to LDAP", + "formname": "Password" + }, + { + "name": "tls_kind", + "validator": self.validators.OneOf(self._tls_kind_values), + "type": "select", + "values": self._tls_kind_values, + "description": "TLS Type", + "default": 'PLAIN', + "formname": "Connection Security" + }, + { + "name": "tls_reqcert", + "validator": self.validators.OneOf(self._tls_reqcert_values), + "type": "select", + "values": self._tls_reqcert_values, + "description": "Require Cert over TLS?", + "formname": "Certificate Checks" + }, + { + "name": "base_dn", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "Base DN to search (e.g., dc=mydomain,dc=com)", + "formname": "Base DN" + }, + { + "name": "filter", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "Filter to narrow results (e.g., ou=Users, etc)", + "formname": "LDAP Search Filter" + }, + { + "name": "search_scope", + "validator": self.validators.OneOf(self._search_scopes), + "type": "select", + "values": self._search_scopes, + "description": "How deep to search LDAP", + "formname": "LDAP Search Scope" + }, + { + "name": "attr_login", + "validator": self.validators.AttrLoginValidator(not_empty=True, strip=True), + "type": "string", + "description": "LDAP Attribute to map to user name", + "formname": "Login Attribute" + }, + { + "name": "attr_firstname", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "LDAP Attribute to map to first name", + "formname": "First Name Attribute" + }, + { + "name": "attr_lastname", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "LDAP Attribute to map to last name", + "formname": "Last Name Attribute" + }, + { + "name": "attr_email", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "LDAP Attribute to map to email address", + "formname": "Email Attribute" + } + ] + return settings + + def use_fake_password(self): + return True + + def user_activation_state(self): + def_user_perms = User.get_default_user().AuthUser.permissions['global'] + return 'hg.extern_activate.auto' in def_user_perms + + def auth(self, userobj, username, password, settings, **kwargs): + """ + Given a user object (which may be null), username, a plaintext password, + and a settings object (containing all the keys needed as listed in settings()), + authenticate this user's login attempt. + + Return None on failure. On success, return a dictionary of the form: + + see: KallitheaAuthPluginBase.auth_func_attrs + This is later validated for correctness + """ + + if not username or not password: + log.debug('Empty username or password skipping...') + return None + + kwargs = { + 'server': settings.get('host', ''), + 'base_dn': settings.get('base_dn', ''), + 'port': settings.get('port'), + 'bind_dn': settings.get('dn_user'), + 'bind_pass': settings.get('dn_pass'), + 'tls_kind': settings.get('tls_kind'), + 'tls_reqcert': settings.get('tls_reqcert'), + 'ldap_filter': settings.get('filter'), + 'search_scope': settings.get('search_scope'), + 'attr_login': settings.get('attr_login'), + 'ldap_version': 3, + } + + if kwargs['bind_dn'] and not kwargs['bind_pass']: + log.debug('Using dynamic binding.') + kwargs['bind_dn'] = kwargs['bind_dn'].replace('$login', username) + kwargs['bind_pass'] = password + log.debug('Checking for ldap authentication') + + try: + aldap = AuthLdap(**kwargs) + (user_dn, ldap_attrs) = aldap.authenticate_ldap(username, password) + log.debug('Got ldap DN response %s' % user_dn) + + get_ldap_attr = lambda k: ldap_attrs.get(settings.get(k), [''])[0] + + # old attrs fetched from Kallithea database + admin = getattr(userobj, 'admin', False) + active = getattr(userobj, 'active', True) + email = getattr(userobj, 'email', '') + firstname = getattr(userobj, 'firstname', '') + lastname = getattr(userobj, 'lastname', '') + extern_type = getattr(userobj, 'extern_type', '') + + user_attrs = { + 'username': username, + 'firstname': safe_unicode(get_ldap_attr('attr_firstname') or firstname), + 'lastname': safe_unicode(get_ldap_attr('attr_lastname') or lastname), + 'groups': [], + 'email': get_ldap_attr('attr_email' or email), + 'admin': admin, + 'active': active, + "active_from_extern": None, + 'extern_name': user_dn, + 'extern_type': extern_type, + } + log.info('user %s authenticated correctly' % user_attrs['username']) + return user_attrs + + except (LdapUsernameError, LdapPasswordError, LdapImportError): + log.error(traceback.format_exc()) + return None + except (Exception,): + log.error(traceback.format_exc()) + return None diff --git a/kallithea/lib/auth_modules/auth_pam.py b/kallithea/lib/auth_modules/auth_pam.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/auth_modules/auth_pam.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.lib.auth_pam +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Kallithea authentication library for PAM + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Created on Apr 09, 2013 +:author: Alexey Larikov +""" + +import logging +import time +import pam +import pwd +import grp +import re +import socket +import threading + +from kallithea.lib import auth_modules +from kallithea.lib.compat import formatted_json, hybrid_property + +log = logging.getLogger(__name__) + +# Cache to store PAM authenticated users +_auth_cache = dict() +_pam_lock = threading.Lock() + + +class KallitheaAuthPlugin(auth_modules.KallitheaExternalAuthPlugin): + # PAM authnetication can be slow. Repository operations involve a lot of + # auth calls. Little caching helps speedup push/pull operations significantly + AUTH_CACHE_TTL = 4 + + def __init__(self): + global _auth_cache + ts = time.time() + cleared_cache = dict( + [(k, v) for (k, v) in _auth_cache.items() if + (v + KallitheaAuthPlugin.AUTH_CACHE_TTL > ts)]) + _auth_cache = cleared_cache + + @hybrid_property + def name(self): + return "pam" + + def settings(self): + settings = [ + { + "name": "service", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "PAM service name to use for authentication", + "default": "login", + "formname": "PAM service name" + }, + { + "name": "gecos", + "validator": self.validators.UnicodeString(strip=True), + "type": "string", + "description": "Regex for extracting user name/email etc " + "from Unix userinfo", + "default": "(?P.+),\s*(?P\w+)", + "formname": "Gecos Regex" + } + ] + return settings + + def use_fake_password(self): + return True + + def auth(self, userobj, username, password, settings, **kwargs): + if username not in _auth_cache: + # Need lock here, as PAM authentication is not thread safe + _pam_lock.acquire() + try: + auth_result = pam.authenticate(username, password, + settings["service"]) + # cache result only if we properly authenticated + if auth_result: + _auth_cache[username] = time.time() + finally: + _pam_lock.release() + + if not auth_result: + log.error("PAM was unable to authenticate user: %s" % (username,)) + return None + else: + log.debug("Using cached auth for user: %s" % (username,)) + + # old attrs fetched from Kallithea database + admin = getattr(userobj, 'admin', False) + active = getattr(userobj, 'active', True) + email = getattr(userobj, 'email', '') or "%s@%s" % (username, socket.gethostname()) + firstname = getattr(userobj, 'firstname', '') + lastname = getattr(userobj, 'lastname', '') + extern_type = getattr(userobj, 'extern_type', '') + + user_attrs = { + 'username': username, + 'firstname': firstname, + 'lastname': lastname, + 'groups': [g.gr_name for g in grp.getgrall() if username in g.gr_mem], + 'email': email, + 'admin': admin, + 'active': active, + "active_from_extern": None, + 'extern_name': username, + 'extern_type': extern_type, + } + + try: + user_data = pwd.getpwnam(username) + regex = settings["gecos"] + match = re.search(regex, user_data.pw_gecos) + if match: + user_attrs["firstname"] = match.group('first_name') + user_attrs["lastname"] = match.group('last_name') + except Exception: + log.warn("Cannot extract additional info for PAM user") + pass + + log.debug("pamuser: \n%s" % formatted_json(user_attrs)) + log.info('user %s authenticated correctly' % user_attrs['username']) + return user_attrs diff --git a/rhodecode/lib/base.py b/kallithea/lib/base.py rename from rhodecode/lib/base.py rename to kallithea/lib/base.py --- a/rhodecode/lib/base.py +++ b/kallithea/lib/base.py @@ -1,7 +1,33 @@ -"""The base Controller API +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . -Provides the BaseController class for subclassing. """ +kallithea.lib.base +~~~~~~~~~~~~~~~~~~ + +The base Controller API +Provides the BaseController class for subclassing. And usage in different +controllers + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Oct 06, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import time import traceback @@ -13,22 +39,22 @@ from paste.httpheaders import WWW_AUTHEN from pylons import config, tmpl_context as c, request, session, url from pylons.controllers import WSGIController from pylons.controllers.util import redirect -from pylons.templating import render_mako as render +from pylons.templating import render_mako as render # don't remove this import -from rhodecode import __version__, BACKENDS +from kallithea import __version__, BACKENDS -from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\ +from kallithea.lib.utils2 import str2bool, safe_unicode, AttributeDict,\ safe_str, safe_int -from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\ - HasPermissionAnyMiddleware, CookieStoreWrapper -from rhodecode.lib.utils import get_repo_slug -from rhodecode.lib.exceptions import UserCreationError -from rhodecode.model import meta +from kallithea.lib import auth_modules +from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware, CookieStoreWrapper +from kallithea.lib.utils import get_repo_slug +from kallithea.lib.exceptions import UserCreationError +from kallithea.model import meta -from rhodecode.model.db import Repository, RhodeCodeUi, User, RhodeCodeSetting -from rhodecode.model.notification import NotificationModel -from rhodecode.model.scm import ScmModel -from rhodecode.model.meta import Session +from kallithea.model.db import Repository, Ui, User, Setting +from kallithea.model.notification import NotificationModel +from kallithea.model.scm import ScmModel +from kallithea.model.meta import Session log = logging.getLogger(__name__) @@ -85,7 +111,7 @@ class BasicAuth(AuthBasicAuthenticator): head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm) if self._rc_auth_http_code and self._rc_auth_http_code == '403': # return 403 if alternative http return code is specified in - # RhodeCode config + # Kallithea config return HTTPForbidden(headers=head) return HTTPUnauthorized(headers=head) @@ -100,7 +126,7 @@ class BasicAuth(AuthBasicAuthenticator): _parts = auth.split(':', 1) if len(_parts) == 2: username, password = _parts - if self.authfunc(environ, username, password): + if self.authfunc(username, password, environ): return username return self.build_authentication() @@ -114,8 +140,8 @@ class BaseVCSController(object): self.config = config # base path of repo locations self.basepath = self.config['base_path'] - #authenticate this mercurial request using authfunc - self.authenticate = BasicAuth('', authfunc, + #authenticate this VCS request using authfunc + self.authenticate = BasicAuth('', auth_modules.authenticate, config.get('auth_ret_code')) self.ip_addr = '0.0.0.0' @@ -129,18 +155,13 @@ class BaseVCSController(object): :param repo_name: """ - try: - data = repo_name.split('/') - if len(data) >= 2: - by_id = data[1].split('_') - if len(by_id) == 2 and by_id[1].isdigit(): - _repo_name = Repository.get(by_id[1]).repo_name - data[1] = _repo_name - except Exception: - log.debug('Failed to extract repo_name from id %s' % ( - traceback.format_exc() - ) - ) + + data = repo_name.split('/') + if len(data) >= 2: + from kallithea.lib.utils import get_repo_by_id + by_id_match = get_repo_by_id(repo_name) + if by_id_match: + data[1] = by_id_match return '/'.join(data) @@ -161,12 +182,15 @@ class BaseVCSController(object): :param user: user instance :param repo_name: repository name """ - #check IP - authuser = AuthUser(user_id=user.user_id, ip_addr=ip_addr) - if not authuser.ip_allowed: + # check IP + inherit = user.inherit_default_permissions + ip_allowed = AuthUser.check_ip_allowed(user.user_id, ip_addr, + inherit_from_default=inherit) + if ip_allowed: + log.info('Access for IP:%s allowed' % (ip_addr,)) + else: return False - else: - log.info('Access for IP:%s allowed' % (ip_addr)) + if action == 'push': if not HasPermissionAnyMiddleware('repository.write', 'repository.admin')(user, @@ -193,7 +217,7 @@ class BaseVCSController(object): """ org_proto = environ['wsgi._org_proto'] #check if we have SSL required ! if not it's a bad request ! - require_ssl = str2bool(RhodeCodeUi.get_by_key('push_ssl').ui_value) + require_ssl = str2bool(Ui.get_by_key('push_ssl').ui_value) if require_ssl and org_proto == 'http': log.debug('proto is %s and SSL is required BAD REQUEST !' % org_proto) @@ -249,7 +273,7 @@ class BaseVCSController(object): try: return self._handle_request(environ, start_response) finally: - log = logging.getLogger('rhodecode.' + self.__class__.__name__) + log = logging.getLogger('kallithea.' + self.__class__.__name__) log.debug('Request time: %.3fs' % (time.time() - start)) meta.Session.remove() @@ -260,32 +284,41 @@ class BaseController(WSGIController): """ __before__ is called before controller methods and after __call__ """ - c.rhodecode_version = __version__ - c.rhodecode_instanceid = config.get('instance_id') - c.rhodecode_name = config.get('rhodecode_title') - c.rhodecode_bugtracker = config.get('bugtracker', 'http://bitbucket.org/marcinkuzminski/rhodecode/issues') - c.use_gravatar = str2bool(config.get('use_gravatar')) - c.ga_code = config.get('rhodecode_ga_code') + c.kallithea_version = __version__ + rc_config = Setting.get_app_settings() + # Visual options c.visual = AttributeDict({}) - rc_config = RhodeCodeSetting.get_app_settings() + ## DB stored - c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon')) - c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon')) - c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags')) - c.visual.dashboard_items = safe_int(rc_config.get('rhodecode_dashboard_items', 100)) - c.visual.repository_fields = str2bool(rc_config.get('rhodecode_repository_fields')) - c.visual.show_version = str2bool(rc_config.get('rhodecode_show_version')) + c.visual.show_public_icon = str2bool(rc_config.get('show_public_icon')) + c.visual.show_private_icon = str2bool(rc_config.get('show_private_icon')) + c.visual.stylify_metatags = str2bool(rc_config.get('stylify_metatags')) + c.visual.dashboard_items = safe_int(rc_config.get('dashboard_items', 100)) + c.visual.admin_grid_items = safe_int(rc_config.get('admin_grid_items', 100)) + c.visual.repository_fields = str2bool(rc_config.get('repository_fields')) + c.visual.show_version = str2bool(rc_config.get('show_version')) + c.visual.use_gravatar = str2bool(rc_config.get('use_gravatar')) + c.visual.gravatar_url = rc_config.get('gravatar_url') + + c.ga_code = rc_config.get('ga_code') + c.site_name = rc_config.get('title') + c.clone_uri_tmpl = rc_config.get('clone_uri_tmpl') ## INI stored - self.cut_off_limit = int(config.get('cut_off_limit')) c.visual.allow_repo_location_change = str2bool(config.get('allow_repo_location_change', True)) c.visual.allow_custom_hooks_settings = str2bool(config.get('allow_custom_hooks_settings', True)) + c.instance_id = config.get('instance_id') + c.issues_url = config.get('bugtracker', url('issues_url')) + # END CONFIG VARS + c.repo_name = get_repo_slug(request) # can be empty c.backends = BACKENDS.keys() c.unread_notifications = NotificationModel()\ - .get_unread_cnt_for_user(c.rhodecode_user.user_id) + .get_unread_cnt_for_user(c.authuser.user_id) + + self.cut_off_limit = safe_int(config.get('cut_off_limit')) self.sa = meta.Session self.scm_model = ScmModel(self.sa) @@ -298,27 +331,33 @@ class BaseController(WSGIController): self.ip_addr = _get_ip_addr(environ) # make sure that we update permissions each time we call controller api_key = request.GET.get('api_key') - cookie_store = CookieStoreWrapper(session.get('rhodecode_user')) - user_id = cookie_store.get('user_id', None) - username = get_container_username(environ, config) - try: - auth_user = AuthUser(user_id, api_key, username, self.ip_addr) - except UserCreationError, e: - from rhodecode.lib import helpers as h - h.flash(e, 'error') - # container auth or other auth functions that create users on - # the fly can throw this exception signaling that there's issue - # with user creation, explanation should be provided in - # Exception itself - auth_user = AuthUser(ip_addr=self.ip_addr) + if api_key: + # when using API_KEY we are sure user exists. + auth_user = AuthUser(api_key=api_key, ip_addr=self.ip_addr) + authenticated = False + else: + cookie_store = CookieStoreWrapper(session.get('authuser')) + try: + auth_user = AuthUser(user_id=cookie_store.get('user_id', None), + ip_addr=self.ip_addr) + except UserCreationError, e: + from kallithea.lib import helpers as h + h.flash(e, 'error') + # container auth or other auth functions that create users on + # the fly can throw this exception signaling that there's issue + # with user creation, explanation should be provided in + # Exception itself + auth_user = AuthUser(ip_addr=self.ip_addr) + + authenticated = cookie_store.get('is_authenticated') + + if not auth_user.is_authenticated and auth_user.user_id is not None: + # user is not authenticated and not empty + auth_user.set_authenticated(authenticated) request.user = auth_user - self.rhodecode_user = c.rhodecode_user = auth_user - if not self.rhodecode_user.is_authenticated and \ - self.rhodecode_user.user_id is not None: - self.rhodecode_user.set_authenticated( - cookie_store.get('is_authenticated') - ) + #set globals for auth user + self.authuser = c.authuser = auth_user log.info('IP: %s User: %s accessed %s' % ( self.ip_addr, auth_user, safe_unicode(_get_access_path(environ))) ) @@ -332,8 +371,8 @@ class BaseRepoController(BaseController) Base class for controllers responsible for loading all needed data for repository loaded items are - c.rhodecode_repo: instance of scm repository - c.rhodecode_db_repo: instance of db + c.db_repo_scm_instance: instance of scm repository + c.db_repo: instance of db c.repository_followers: number of followers c.repository_forks: number of forks c.repository_following: weather the current user is following the current repo @@ -341,21 +380,39 @@ class BaseRepoController(BaseController) def __before__(self): super(BaseRepoController, self).__before__() - if c.repo_name: + if c.repo_name: # extracted from routes + _dbr = Repository.get_by_repo_name(c.repo_name) + if not _dbr: + return + + log.debug('Found repository in database %s with state `%s`' + % (safe_unicode(_dbr), safe_unicode(_dbr.repo_state))) + route = getattr(request.environ.get('routes.route'), 'name', '') - dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name) - c.rhodecode_repo = c.rhodecode_db_repo.scm_instance - # update last change according to VCS data - dbr.update_changeset_cache(dbr.get_changeset()) - if c.rhodecode_repo is None: + # allow to delete repos that are somehow damages in filesystem + if route in ['delete_repo']: + return + + if _dbr.repo_state in [Repository.STATE_PENDING]: + if route in ['repo_creating_home']: + return + check_url = url('repo_creating_home', repo_name=c.repo_name) + return redirect(check_url) + + dbr = c.db_repo = _dbr + c.db_repo_scm_instance = c.db_repo.scm_instance + if c.db_repo_scm_instance is None: log.error('%s this repository is present in database but it ' 'cannot be created as an scm instance', c.repo_name) redirect(url('home')) + # update last change according to VCS data + dbr.update_changeset_cache(dbr.get_changeset()) + # some globals counter for menu c.repository_followers = self.scm_model.get_followers(dbr) c.repository_forks = self.scm_model.get_forks(dbr) c.repository_pull_requests = self.scm_model.get_pull_requests(dbr) - c.repository_following = self.scm_model.is_following_repo(c.repo_name, - self.rhodecode_user.user_id) + c.repository_following = self.scm_model.is_following_repo( + c.repo_name, self.authuser.user_id) diff --git a/rhodecode/lib/caching_query.py b/kallithea/lib/caching_query.py rename from rhodecode/lib/caching_query.py rename to kallithea/lib/caching_query.py --- a/rhodecode/lib/caching_query.py +++ b/kallithea/lib/caching_query.py @@ -24,7 +24,7 @@ from beaker.exceptions import BeakerExce from sqlalchemy.orm.interfaces import MapperOption from sqlalchemy.orm.query import Query from sqlalchemy.sql import visitors -from rhodecode.lib.utils2 import safe_str +from kallithea.lib.utils2 import safe_str class CachingQuery(Query): diff --git a/rhodecode/lib/celerylib/__init__.py b/kallithea/lib/celerylib/__init__.py rename from rhodecode/lib/celerylib/__init__.py rename to kallithea/lib/celerylib/__init__.py --- a/rhodecode/lib/celerylib/__init__.py +++ b/kallithea/lib/celerylib/__init__.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.celerylib.__init__ - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - celery libs for RhodeCode - - :created_on: Nov 27, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.celerylib.__init__ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +celery libs for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Nov 27, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import os import sys @@ -34,13 +37,13 @@ from pylons import config from hashlib import md5 from decorator import decorator -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode import CELERY_ON, CELERY_EAGER -from rhodecode.lib.utils2 import str2bool, safe_str -from rhodecode.lib.pidlock import DaemonLock, LockHeld -from rhodecode.model import init_model -from rhodecode.model import meta -from rhodecode.model.db import Statistics, Repository, User +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea import CELERY_ON, CELERY_EAGER +from kallithea.lib.utils2 import str2bool, safe_str +from kallithea.lib.pidlock import DaemonLock, LockHeld +from kallithea.model import init_model +from kallithea.model import meta +from kallithea.model.db import Statistics, Repository, User from sqlalchemy import engine_from_config diff --git a/rhodecode/lib/celerylib/tasks.py b/kallithea/lib/celerylib/tasks.py rename from rhodecode/lib/celerylib/tasks.py rename to kallithea/lib/celerylib/tasks.py --- a/rhodecode/lib/celerylib/tasks.py +++ b/kallithea/lib/celerylib/tasks.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.celerylib.tasks - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - RhodeCode task modules, containing all task that suppose to be run - by celery daemon - - :created_on: Oct 6, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,6 +11,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.celerylib.tasks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Kallithea task modules, containing all task that suppose to be run +by celery daemon + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Oct 6, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from celery.decorators import task import os @@ -37,23 +40,23 @@ from string import lower from pylons import config, url from pylons.i18n.translation import _ -from rhodecode.lib.vcs import get_backend +from kallithea.lib.vcs import get_backend -from rhodecode import CELERY_ON, CELERY_EAGER -from rhodecode.lib.utils2 import safe_str -from rhodecode.lib.celerylib import run_task, locked_task, dbsession, \ +from kallithea import CELERY_ON, CELERY_EAGER +from kallithea.lib.utils2 import safe_str +from kallithea.lib.celerylib import run_task, locked_task, dbsession, \ str2bool, __get_lockkey, LockHeld, DaemonLock, get_session -from rhodecode.lib.helpers import person -from rhodecode.lib.rcmail.smtp_mailer import SmtpMailer -from rhodecode.lib.utils import add_cache, action_logger -from rhodecode.lib.compat import json, OrderedDict -from rhodecode.lib.hooks import log_create_repository +from kallithea.lib.helpers import person +from kallithea.lib.rcmail.smtp_mailer import SmtpMailer +from kallithea.lib.utils import add_cache, action_logger +from kallithea.lib.compat import json, OrderedDict +from kallithea.lib.hooks import log_create_repository -from rhodecode.model.db import Statistics, Repository, User -from rhodecode.model.scm import ScmModel +from kallithea.model.db import Statistics, Repository, User +from kallithea.model.scm import ScmModel -add_cache(config) +add_cache(config) # pragma: no cover __all__ = ['whoosh_index', 'get_commits_stats', 'reset_user_password', 'send_email'] @@ -63,7 +66,7 @@ def get_logger(cls): if CELERY_ON: try: log = cls.get_logger() - except: + except Exception: log = logging.getLogger(__name__) else: log = logging.getLogger(__name__) @@ -75,7 +78,7 @@ def get_logger(cls): @locked_task @dbsession def whoosh_index(repo_location, full_index): - from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon + from kallithea.lib.indexers.daemon import WhooshIndexingDaemon log = get_logger(whoosh_index) DBS = get_session() @@ -275,7 +278,7 @@ def send_email(recipients, subject, body .filter(User.admin == True).all()] recipients = [email_config.get('email_to')] + admins - mail_from = email_config.get('app_email_from', 'RhodeCode') + mail_from = email_config.get('app_email_from', 'Kallithea') user = email_config.get('smtp_username') passwd = email_config.get('smtp_password') mail_server = email_config.get('smtp_server') @@ -299,8 +302,96 @@ def send_email(recipients, subject, body return False return True +@task(ignore_result=False) +@dbsession +def create_repo(form_data, cur_user): + from kallithea.model.repo import RepoModel + from kallithea.model.user import UserModel + from kallithea.model.db import Setting -@task(ignore_result=True) + log = get_logger(create_repo) + DBS = get_session() + + cur_user = UserModel(DBS)._get_user(cur_user) + + owner = cur_user + repo_name = form_data['repo_name'] + repo_name_full = form_data['repo_name_full'] + repo_type = form_data['repo_type'] + description = form_data['repo_description'] + private = form_data['repo_private'] + clone_uri = form_data.get('clone_uri') + repo_group = form_data['repo_group'] + landing_rev = form_data['repo_landing_rev'] + copy_fork_permissions = form_data.get('copy_permissions') + copy_group_permissions = form_data.get('repo_copy_permissions') + fork_of = form_data.get('fork_parent_id') + state = form_data.get('repo_state', Repository.STATE_PENDING) + + # repo creation defaults, private and repo_type are filled in form + defs = Setting.get_default_repo_settings(strip_prefix=True) + enable_statistics = defs.get('repo_enable_statistics') + enable_locking = defs.get('repo_enable_locking') + enable_downloads = defs.get('repo_enable_downloads') + + try: + repo = RepoModel(DBS)._create_repo( + repo_name=repo_name_full, + repo_type=repo_type, + description=description, + owner=owner, + private=private, + clone_uri=clone_uri, + repo_group=repo_group, + landing_rev=landing_rev, + fork_of=fork_of, + copy_fork_permissions=copy_fork_permissions, + copy_group_permissions=copy_group_permissions, + enable_statistics=enable_statistics, + enable_locking=enable_locking, + enable_downloads=enable_downloads, + state=state + ) + + action_logger(cur_user, 'user_created_repo', + form_data['repo_name_full'], '', DBS) + + DBS.commit() + # now create this repo on Filesystem + RepoModel(DBS)._create_filesystem_repo( + repo_name=repo_name, + repo_type=repo_type, + repo_group=RepoModel(DBS)._get_repo_group(repo_group), + clone_uri=clone_uri, + ) + repo = Repository.get_by_repo_name(repo_name_full) + log_create_repository(repo.get_dict(), created_by=owner.username) + + # update repo changeset caches initially + repo.update_changeset_cache() + + # set new created state + repo.set_state(Repository.STATE_CREATED) + DBS.commit() + except Exception, e: + log.warning('Exception %s occured when forking repository, ' + 'doing cleanup...' % e) + # rollback things manually ! + repo = Repository.get_by_repo_name(repo_name_full) + if repo: + Repository.delete(repo.repo_id) + DBS.commit() + RepoModel(DBS)._delete_filesystem_repo(repo) + raise + + # it's an odd fix to make celery fail task when exception occurs + def on_failure(self, *args, **kwargs): + pass + + return True + + +@task(ignore_result=False) @dbsession def create_repo_fork(form_data, cur_user): """ @@ -309,8 +400,8 @@ def create_repo_fork(form_data, cur_user :param form_data: :param cur_user: """ - from rhodecode.model.repo import RepoModel - from rhodecode.model.user import UserModel + from kallithea.model.repo import RepoModel + from kallithea.model.user import UserModel log = get_logger(create_repo_fork) DBS = get_session() @@ -318,60 +409,75 @@ def create_repo_fork(form_data, cur_user base_path = Repository.base_path() cur_user = UserModel(DBS)._get_user(cur_user) - fork_name = form_data['repo_name_full'] + repo_name = form_data['repo_name'] # fork in this case + repo_name_full = form_data['repo_name_full'] + repo_type = form_data['repo_type'] - description = form_data['description'] owner = cur_user private = form_data['private'] clone_uri = form_data.get('clone_uri') - repos_group = form_data['repo_group'] + repo_group = form_data['repo_group'] landing_rev = form_data['landing_rev'] copy_fork_permissions = form_data.get('copy_permissions') - fork_of = RepoModel(DBS)._get_repo(form_data.get('fork_parent_id')) - fork_repo = RepoModel(DBS).create_repo( - fork_name, repo_type, description, owner, private, clone_uri, - repos_group, landing_rev, just_db=True, fork_of=fork_of, - copy_fork_permissions=copy_fork_permissions - ) + try: + fork_of = RepoModel(DBS)._get_repo(form_data.get('fork_parent_id')) - update_after_clone = form_data['update_after_clone'] + fork_repo = RepoModel(DBS)._create_repo( + repo_name=repo_name_full, + repo_type=repo_type, + description=form_data['description'], + owner=owner, + private=private, + clone_uri=clone_uri, + repo_group=repo_group, + landing_rev=landing_rev, + fork_of=fork_of, + copy_fork_permissions=copy_fork_permissions + ) + action_logger(cur_user, 'user_forked_repo:%s' % repo_name_full, + fork_of.repo_name, '', DBS) + DBS.commit() - source_repo_path = os.path.join(base_path, fork_of.repo_name) - destination_fork_path = os.path.join(base_path, fork_name) - - log.info('creating fork of %s as %s', source_repo_path, - destination_fork_path) - backend = get_backend(repo_type) + update_after_clone = form_data['update_after_clone'] + source_repo_path = os.path.join(base_path, fork_of.repo_name) - if repo_type == 'git': - r = backend(safe_str(destination_fork_path), create=True, - src_url=safe_str(source_repo_path), - update_after_clone=update_after_clone, - bare=True) - # add rhodecode hook into this repo - ScmModel().install_git_hook(repo=r) - elif repo_type == 'hg': - r = backend(safe_str(destination_fork_path), create=True, - src_url=safe_str(source_repo_path), - update_after_clone=update_after_clone) - else: - raise Exception('Unknown backend type %s' % repo_type) + # now create this repo on Filesystem + RepoModel(DBS)._create_filesystem_repo( + repo_name=repo_name, + repo_type=repo_type, + repo_group=RepoModel(DBS)._get_repo_group(repo_group), + clone_uri=source_repo_path, + ) + repo = Repository.get_by_repo_name(repo_name_full) + log_create_repository(repo.get_dict(), created_by=owner.username) + + # update repo changeset caches initially + repo.update_changeset_cache() - log_create_repository(fork_repo.get_dict(), created_by=cur_user.username) - - action_logger(cur_user, 'user_forked_repo:%s' % fork_name, - fork_of.repo_name, '', DBS) + # set new created state + repo.set_state(Repository.STATE_CREATED) + DBS.commit() + except Exception, e: + log.warning('Exception %s occured when forking repository, ' + 'doing cleanup...' % e) + #rollback things manually ! + repo = Repository.get_by_repo_name(repo_name_full) + if repo: + Repository.delete(repo.repo_id) + DBS.commit() + RepoModel(DBS)._delete_filesystem_repo(repo) + raise - action_logger(cur_user, 'user_created_fork:%s' % fork_name, - fork_name, '', DBS) - # finally commit at latest possible stage - DBS.commit() - fork_repo.update_changeset_cache() + # it's an odd fix to make celery fail task when exception occurs + def on_failure(self, *args, **kwargs): + pass + + return True def __get_codes_stats(repo_name): - from rhodecode.config.conf import LANGUAGES_EXTENSIONS_MAP + from kallithea.config.conf import LANGUAGES_EXTENSIONS_MAP repo = Repository.get_by_repo_name(repo_name).scm_instance tip = repo.get_changeset() diff --git a/rhodecode/lib/celerypylons/__init__.py b/kallithea/lib/celerypylons/__init__.py rename from rhodecode/lib/celerypylons/__init__.py rename to kallithea/lib/celerypylons/__init__.py --- a/rhodecode/lib/celerypylons/__init__.py +++ b/kallithea/lib/celerypylons/__init__.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + """ Automatically sets the environment variable `CELERY_LOADER` to `celerypylons.loader:PylonsLoader`. This ensures the loader is @@ -7,10 +9,11 @@ to be installed in a webapp just by impo import celerypylons """ + import os import warnings -CELERYPYLONS_LOADER = 'rhodecode.lib.celerypylons.loader.PylonsLoader' +CELERYPYLONS_LOADER = 'kallithea.lib.celerypylons.loader.PylonsLoader' if os.environ.get('CELERY_LOADER', CELERYPYLONS_LOADER) != CELERYPYLONS_LOADER: warnings.warn("'CELERY_LOADER' environment variable will be overridden by celery-pylons.") os.environ['CELERY_LOADER'] = CELERYPYLONS_LOADER diff --git a/rhodecode/lib/celerypylons/commands.py b/kallithea/lib/celerypylons/commands.py rename from rhodecode/lib/celerypylons/commands.py rename to kallithea/lib/celerypylons/commands.py --- a/rhodecode/lib/celerypylons/commands.py +++ b/kallithea/lib/celerypylons/commands.py @@ -1,9 +1,11 @@ -import rhodecode -from rhodecode.lib.utils import BasePasterCommand, Command, load_rcextensions +# -*- coding: utf-8 -*- + +import kallithea +from kallithea.lib.utils import BasePasterCommand, Command, load_rcextensions from celery.app import app_or_default from celery.bin import camqadm, celerybeat, celeryd, celeryev -from rhodecode.lib.utils2 import str2bool +from kallithea.lib.utils2 import str2bool __all__ = ['CeleryDaemonCommand', 'CeleryBeatCommand', 'CAMQPAdminCommand', 'CeleryEventCommand'] @@ -36,9 +38,9 @@ class CeleryCommand(BasePasterCommand): CELERY_ON = False if not CELERY_ON: - raise Exception('Please enable celery_on in .ini config ' + raise Exception('Please set use_celery = true in .ini config ' 'file before running celeryd') - rhodecode.CELERY_ON = CELERY_ON + kallithea.CELERY_ON = CELERY_ON load_rcextensions(config['here']) cmd = self.celery_command(app_or_default()) return cmd.run(**vars(self.options)) diff --git a/rhodecode/lib/celerypylons/loader.py b/kallithea/lib/celerypylons/loader.py rename from rhodecode/lib/celerypylons/loader.py rename to kallithea/lib/celerypylons/loader.py --- a/rhodecode/lib/celerypylons/loader.py +++ b/kallithea/lib/celerypylons/loader.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + from celery.loaders.base import BaseLoader from pylons import config diff --git a/rhodecode/lib/colored_formatter.py b/kallithea/lib/colored_formatter.py rename from rhodecode/lib/colored_formatter.py rename to kallithea/lib/colored_formatter.py --- a/rhodecode/lib/colored_formatter.py +++ b/kallithea/lib/colored_formatter.py @@ -1,3 +1,16 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import logging diff --git a/rhodecode/lib/compat.py b/kallithea/lib/compat.py rename from rhodecode/lib/compat.py rename to kallithea/lib/compat.py --- a/rhodecode/lib/compat.py +++ b/kallithea/lib/compat.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.compat - ~~~~~~~~~~~~~~~~~~~~ - - Python backward compatibility functions and common libs - - - :created_on: Oct 7, 2011 - :author: marcink - :copyright: (C) 2010-2010 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,14 +11,34 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.compat +~~~~~~~~~~~~~~~~~~~~ + +Python backward compatibility functions and common libs + + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Oct 7, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import os -from rhodecode import __py_version__, is_windows +import functools +import importlib +from kallithea import __py_version__, is_windows #============================================================================== # json #============================================================================== -from rhodecode.lib.ext_json import json +from kallithea.lib.ext_json import json + +# alias for formatted json +formatted_json = functools.partial(json.dumps, indent=4, sort_keys=True) if __py_version__ >= (2, 7): import unittest @@ -367,6 +375,12 @@ from sqlalchemy.util import OrderedSet #============================================================================== +# Hybrid property/method +#============================================================================== +from sqlalchemy.ext.hybrid import hybrid_method, hybrid_property + + +#============================================================================== # kill FUNCTIONS #============================================================================== if is_windows: diff --git a/rhodecode/lib/db_manage.py b/kallithea/lib/db_manage.py rename from rhodecode/lib/db_manage.py rename to kallithea/lib/db_manage.py --- a/rhodecode/lib/db_manage.py +++ b/kallithea/lib/db_manage.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.db_manage - ~~~~~~~~~~~~~~~~~~~~~~~ - - Database creation, and setup module for RhodeCode. Used for creation - of database as well as for migration operations - - :created_on: Apr 10, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.db_manage +~~~~~~~~~~~~~~~~~~~~~~~ + +Database creation, and setup module for Kallithea. Used for creation +of database as well as for migration operations + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 10, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import os import sys @@ -32,22 +34,21 @@ import logging from os.path import dirname as dn, join as jn import datetime -from rhodecode import __dbversion__, __py_version__ - -from rhodecode.model.user import UserModel -from rhodecode.lib.utils import ask_ok -from rhodecode.model import init_model -from rhodecode.model.db import User, Permission, RhodeCodeUi, \ - RhodeCodeSetting, UserToPerm, DbMigrateVersion, RepoGroup, \ - UserRepoGroupToPerm, CacheInvalidation, UserGroup +from kallithea import __dbversion__, __py_version__, EXTERN_TYPE_INTERNAL, DB_MIGRATIONS +from kallithea.model.user import UserModel +from kallithea.lib.utils import ask_ok +from kallithea.model import init_model +from kallithea.model.db import User, Permission, Ui, \ + Setting, UserToPerm, DbMigrateVersion, RepoGroup, \ + UserRepoGroupToPerm, CacheInvalidation, UserGroup, Repository from sqlalchemy.engine import create_engine -from rhodecode.model.repos_group import ReposGroupModel -#from rhodecode.model import meta -from rhodecode.model.meta import Session, Base -from rhodecode.model.repo import RepoModel -from rhodecode.model.permission import PermissionModel -from rhodecode.model.users_group import UserGroupModel +from kallithea.model.repo_group import RepoGroupModel +#from kallithea.model import meta +from kallithea.model.meta import Session, Base +from kallithea.model.repo import RepoModel +from kallithea.model.permission import PermissionModel +from kallithea.model.user_group import UserGroupModel log = logging.getLogger(__name__) @@ -61,172 +62,8 @@ def notify(msg): print('\n%s\n*** %s ***\n%s' % ('*' * ml, msg, '*' * ml)).upper() -class UpgradeSteps(object): - """ - Those steps follow schema versions so for example schema - for example schema with seq 002 == step_2 and so on. - """ - - def __init__(self, klass): - self.klass = klass - - def step_1(self): - pass - - def step_2(self): - notify('Patching repo paths for newer version of RhodeCode') - self.klass.fix_repo_paths() - - notify('Patching default user of RhodeCode') - self.klass.fix_default_user() - - log.info('Changing ui settings') - self.klass.create_ui_settings() - - def step_3(self): - notify('Adding additional settings into RhodeCode db') - self.klass.fix_settings() - notify('Adding ldap defaults') - self.klass.create_ldap_options(skip_existing=True) - - def step_4(self): - notify('create permissions and fix groups') - self.klass.create_permissions() - self.klass.fixup_groups() - - def step_5(self): - pass - - def step_6(self): - - notify('re-checking permissions') - self.klass.create_permissions() - - notify('installing new UI options') - sett4 = RhodeCodeSetting('show_public_icon', True) - Session().add(sett4) - sett5 = RhodeCodeSetting('show_private_icon', True) - Session().add(sett5) - sett6 = RhodeCodeSetting('stylify_metatags', False) - Session().add(sett6) - - notify('fixing old PULL hook') - _pull = RhodeCodeUi.get_by_key('preoutgoing.pull_logger') - if _pull: - _pull.ui_key = RhodeCodeUi.HOOK_PULL - Session().add(_pull) - - notify('fixing old PUSH hook') - _push = RhodeCodeUi.get_by_key('pretxnchangegroup.push_logger') - if _push: - _push.ui_key = RhodeCodeUi.HOOK_PUSH - Session().add(_push) - - notify('installing new pre-push hook') - hooks4 = RhodeCodeUi() - hooks4.ui_section = 'hooks' - hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH - hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push' - Session().add(hooks4) - - notify('installing new pre-pull hook') - hooks6 = RhodeCodeUi() - hooks6.ui_section = 'hooks' - hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL - hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull' - Session().add(hooks6) - - notify('installing hgsubversion option') - # enable hgsubversion disabled by default - hgsubversion = RhodeCodeUi() - hgsubversion.ui_section = 'extensions' - hgsubversion.ui_key = 'hgsubversion' - hgsubversion.ui_value = '' - hgsubversion.ui_active = False - Session().add(hgsubversion) - - notify('installing hg git option') - # enable hggit disabled by default - hggit = RhodeCodeUi() - hggit.ui_section = 'extensions' - hggit.ui_key = 'hggit' - hggit.ui_value = '' - hggit.ui_active = False - Session().add(hggit) - - notify('re-check default permissions') - default_user = User.get_by_username(User.DEFAULT_USER) - perm = Permission.get_by_key('hg.fork.repository') - reg_perm = UserToPerm() - reg_perm.user = default_user - reg_perm.permission = perm - Session().add(reg_perm) - - def step_7(self): - perm_fixes = self.klass.reset_permissions(User.DEFAULT_USER) - Session().commit() - if perm_fixes: - notify('There was an inconsistent state of permissions ' - 'detected for default user. Permissions are now ' - 'reset to the default value for default user. ' - 'Please validate and check default permissions ' - 'in admin panel') - - def step_8(self): - self.klass.create_permissions() - self.klass.populate_default_permissions() - self.klass.create_default_options(skip_existing=True) - Session().commit() - - def step_9(self): - pass - - def step_10(self): - pass - - def step_11(self): - self.klass.update_repo_info() - - def step_12(self): - self.klass.create_permissions() - Session().commit() - - self.klass.populate_default_permissions() - Session().commit() - - #fix all usergroups - ug_model = UserGroupModel() - for ug in UserGroup.get_all(): - perm_obj = ug_model._create_default_perms(ug) - Session().add(perm_obj) - Session().commit() - - adm = User.get_first_admin() - # fix owners of UserGroup - for ug in Session().query(UserGroup).all(): - ug.user_id = adm.user_id - Session().add(ug) - Session().commit() - - # fix owners of RepoGroup - for ug in Session().query(RepoGroup).all(): - ug.user_id = adm.user_id - Session().add(ug) - Session().commit() - - def step_13(self): - pass - - def step_14(self): - # fix nullable columns on last_update - for r in RepoModel().get_all(): - if r.updated_on is None: - r.updated_on = datetime.datetime.fromtimestamp(0) - Session().add(r) - Session().commit() - class DbManage(object): - def __init__(self, log_sql, dbconf, root, tests=False, cli_args={}): + def __init__(self, log_sql, dbconf, root, tests=False, SESSION=None, cli_args={}): self.dbname = dbconf.split('/')[-1] self.tests = tests self.root = root @@ -234,17 +71,21 @@ class DbManage(object): self.log_sql = log_sql self.db_exists = False self.cli_args = cli_args - self.init_db() + self.init_db(SESSION=SESSION) force_ask = self.cli_args.get('force_ask') if force_ask is not None: global ask_ok ask_ok = lambda *args, **kwargs: force_ask - def init_db(self): - engine = create_engine(self.dburi, echo=self.log_sql) - init_model(engine) - self.sa = Session() + def init_db(self, SESSION=None): + if SESSION: + self.sa = SESSION + else: + #init new sessions + engine = create_engine(self.dburi, echo=self.log_sql) + init_model(engine) + self.sa = Session() def create_tables(self, override=False): """ @@ -257,7 +98,8 @@ class DbManage(object): else: destroy = ask_ok('Are you sure to destroy old database ? [y/n]') if not destroy: - sys.exit('Nothing tables created') + print 'Nothing done.' + sys.exit(0) if destroy: Base.metadata.drop_all() @@ -268,7 +110,7 @@ class DbManage(object): def set_db_version(self): ver = DbMigrateVersion() ver.version = __dbversion__ - ver.repository_id = 'rhodecode_db_migrations' + ver.repository_id = DB_MIGRATIONS ver.repository_path = 'versions' self.sa.add(ver) log.info('db version set to: %s' % __dbversion__) @@ -280,8 +122,8 @@ class DbManage(object): """ - from rhodecode.lib.dbmigrate.migrate.versioning import api - from rhodecode.lib.dbmigrate.migrate.exceptions import \ + from kallithea.lib.dbmigrate.migrate.versioning import api + from kallithea.lib.dbmigrate.migrate.exceptions import \ DatabaseNotControlledError if 'sqlite' in self.dburi: @@ -289,33 +131,34 @@ class DbManage(object): '********************** WARNING **********************\n' 'Make sure your version of sqlite is at least 3.7.X. \n' 'Earlier versions are known to fail on some migrations\n' - '*****************************************************\n' - ) + '*****************************************************\n') + upgrade = ask_ok('You are about to perform database upgrade, make ' 'sure You backed up your database before. ' 'Continue ? [y/n]') if not upgrade: - sys.exit('No upgrade performed') + print 'No upgrade performed' + sys.exit(0) repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))), - 'rhodecode/lib/dbmigrate') + 'kallithea/lib/dbmigrate') db_uri = self.dburi try: curr_version = api.db_version(db_uri, repository_path) - msg = ('Found current database under version' - ' control with version %s' % curr_version) + msg = ('Found current database under version ' + 'control with version %s' % curr_version) except (RuntimeError, DatabaseNotControlledError): curr_version = 1 - msg = ('Current database is not under version control. Setting' - ' as version %s' % curr_version) + msg = ('Current database is not under version control. Setting ' + 'as version %s' % curr_version) api.version_control(db_uri, repository_path, curr_version) notify(msg) - if curr_version == __dbversion__: - sys.exit('This database is already at the newest version') + print 'This database is already at the newest version' + sys.exit(0) # clear cache keys log.info("Clearing cache keys now...") @@ -329,27 +172,22 @@ class DbManage(object): _step = None for step in upgrade_steps: notify('performing upgrade step %s' % step) - time.sleep(2) + time.sleep(0.5) api.upgrade(db_uri, repository_path, step) notify('schema upgrade for step %s completed' % (step,)) - fixture = 'step_%s' % step - notify('performing fixture step %s' % fixture) - getattr(UpgradeSteps(self), fixture)() - self.sa.commit() - notify('fixture %s completed' % (fixture,)) _step = step notify('upgrade to version %s successful' % _step) def fix_repo_paths(self): """ - Fixes a old rhodecode version path into new one without a '*' + Fixes a old kallithea version path into new one without a '*' """ - paths = self.sa.query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == '/')\ + paths = self.sa.query(Ui)\ + .filter(Ui.ui_key == '/')\ .scalar() paths.ui_value = paths.ui_value.replace('*', '') @@ -367,12 +205,12 @@ class DbManage(object): used mostly for anonymous access """ def_user = self.sa.query(User)\ - .filter(User.username == 'default')\ + .filter(User.username == User.DEFAULT_USER)\ .one() def_user.name = 'Anonymous' def_user.lastname = 'User' - def_user.email = 'anonymous@rhodecode.org' + def_user.email = 'anonymous@kallithea-scm.org' try: self.sa.add(def_user) @@ -383,10 +221,10 @@ class DbManage(object): def fix_settings(self): """ - Fixes rhodecode settings adds ga_code key for google analytics + Fixes kallithea settings adds ga_code key for google analytics """ - hgsettings3 = RhodeCodeSetting('ga_code', '') + hgsettings3 = Setting('ga_code', '') try: self.sa.add(hgsettings3) @@ -432,7 +270,7 @@ class DbManage(object): self.create_user(username, password, email, True) else: log.info('creating admin and regular test users') - from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \ + from kallithea.tests import TEST_USER_ADMIN_LOGIN, \ TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \ TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \ TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \ @@ -447,66 +285,75 @@ class DbManage(object): self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL, False) - def create_ui_settings(self): + def create_ui_settings(self, repo_store_path): """ Creates ui settings, fills out hooks and disables dotencode """ #HOOKS - hooks1_key = RhodeCodeUi.HOOK_UPDATE - hooks1_ = self.sa.query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == hooks1_key).scalar() + hooks1_key = Ui.HOOK_UPDATE + hooks1_ = self.sa.query(Ui)\ + .filter(Ui.ui_key == hooks1_key).scalar() - hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_ + hooks1 = Ui() if hooks1_ is None else hooks1_ hooks1.ui_section = 'hooks' hooks1.ui_key = hooks1_key hooks1.ui_value = 'hg update >&2' hooks1.ui_active = False self.sa.add(hooks1) - hooks2_key = RhodeCodeUi.HOOK_REPO_SIZE - hooks2_ = self.sa.query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == hooks2_key).scalar() - hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_ + hooks2_key = Ui.HOOK_REPO_SIZE + hooks2_ = self.sa.query(Ui)\ + .filter(Ui.ui_key == hooks2_key).scalar() + hooks2 = Ui() if hooks2_ is None else hooks2_ hooks2.ui_section = 'hooks' hooks2.ui_key = hooks2_key - hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size' + hooks2.ui_value = 'python:kallithea.lib.hooks.repo_size' self.sa.add(hooks2) - hooks3 = RhodeCodeUi() + hooks3 = Ui() hooks3.ui_section = 'hooks' - hooks3.ui_key = RhodeCodeUi.HOOK_PUSH - hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action' + hooks3.ui_key = Ui.HOOK_PUSH + hooks3.ui_value = 'python:kallithea.lib.hooks.log_push_action' self.sa.add(hooks3) - hooks4 = RhodeCodeUi() + hooks4 = Ui() hooks4.ui_section = 'hooks' - hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH - hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push' + hooks4.ui_key = Ui.HOOK_PRE_PUSH + hooks4.ui_value = 'python:kallithea.lib.hooks.pre_push' self.sa.add(hooks4) - hooks5 = RhodeCodeUi() + hooks5 = Ui() hooks5.ui_section = 'hooks' - hooks5.ui_key = RhodeCodeUi.HOOK_PULL - hooks5.ui_value = 'python:rhodecode.lib.hooks.log_pull_action' + hooks5.ui_key = Ui.HOOK_PULL + hooks5.ui_value = 'python:kallithea.lib.hooks.log_pull_action' self.sa.add(hooks5) - hooks6 = RhodeCodeUi() + hooks6 = Ui() hooks6.ui_section = 'hooks' - hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL - hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull' + hooks6.ui_key = Ui.HOOK_PRE_PULL + hooks6.ui_value = 'python:kallithea.lib.hooks.pre_pull' self.sa.add(hooks6) # enable largefiles - largefiles = RhodeCodeUi() + largefiles = Ui() largefiles.ui_section = 'extensions' largefiles.ui_key = 'largefiles' largefiles.ui_value = '' self.sa.add(largefiles) + # set default largefiles cache dir, defaults to + # /repo location/.cache/largefiles + largefiles = Ui() + largefiles.ui_section = 'largefiles' + largefiles.ui_key = 'usercache' + largefiles.ui_value = os.path.join(repo_store_path, '.cache', + 'largefiles') + self.sa.add(largefiles) + # enable hgsubversion disabled by default - hgsubversion = RhodeCodeUi() + hgsubversion = Ui() hgsubversion.ui_section = 'extensions' hgsubversion.ui_key = 'hgsubversion' hgsubversion.ui_value = '' @@ -514,44 +361,42 @@ class DbManage(object): self.sa.add(hgsubversion) # enable hggit disabled by default - hggit = RhodeCodeUi() + hggit = Ui() hggit.ui_section = 'extensions' hggit.ui_key = 'hggit' hggit.ui_value = '' hggit.ui_active = False self.sa.add(hggit) - def create_ldap_options(self, skip_existing=False): - """Creates ldap settings""" + def create_auth_plugin_options(self, skip_existing=False): + """ + Create default auth plugin settings, and make it active - for k, v in [('ldap_active', 'false'), ('ldap_host', ''), - ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'), - ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''), - ('ldap_dn_pass', ''), ('ldap_base_dn', ''), - ('ldap_filter', ''), ('ldap_search_scope', ''), - ('ldap_attr_login', ''), ('ldap_attr_firstname', ''), - ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]: + :param skip_existing: + """ - if skip_existing and RhodeCodeSetting.get_by_name(k) is not None: + for k, v, t in [('auth_plugins', 'kallithea.lib.auth_modules.auth_internal', 'list'), + ('auth_internal_enabled', 'True', 'bool')]: + if skip_existing and Setting.get_by_name(k) != None: log.debug('Skipping option %s' % k) continue - setting = RhodeCodeSetting(k, v) + setting = Setting(k, v, t) self.sa.add(setting) def create_default_options(self, skip_existing=False): """Creates default settings""" - for k, v in [ - ('default_repo_enable_locking', False), - ('default_repo_enable_downloads', False), - ('default_repo_enable_statistics', False), - ('default_repo_private', False), - ('default_repo_type', 'hg')]: + for k, v, t in [ + ('default_repo_enable_locking', False, 'bool'), + ('default_repo_enable_downloads', False, 'bool'), + ('default_repo_enable_statistics', False, 'bool'), + ('default_repo_private', False, 'bool'), + ('default_repo_type', 'hg', 'unicode')]: - if skip_existing and RhodeCodeSetting.get_by_name(k) is not None: + if skip_existing and Setting.get_by_name(k) is not None: log.debug('Skipping option %s' % k) continue - setting = RhodeCodeSetting(k, v) + setting = Setting(k, v, t) self.sa.add(setting) def fixup_groups(self): @@ -567,7 +412,7 @@ class DbManage(object): if default is None: log.debug('missing default permission for group %s adding' % g) - perm_obj = ReposGroupModel()._create_default_perms(g) + perm_obj = RepoGroupModel()._create_default_perms(g) self.sa.add(perm_obj) def reset_permissions(self, username): @@ -642,7 +487,7 @@ class DbManage(object): real_path = os.path.normpath(os.path.realpath(path)) if real_path != os.path.normpath(path): - if not ask_ok(('Path looks like a symlink, Rhodecode will store ' + if not ask_ok(('Path looks like a symlink, Kallithea will store ' 'given path as %s ? [y/n]') % (real_path,)): log.error('Canceled by user') sys.exit(-1) @@ -651,7 +496,7 @@ class DbManage(object): def create_settings(self, path): - self.create_ui_settings() + self.create_ui_settings(path) ui_config = [ ('web', 'push_ssl', 'false'), @@ -662,27 +507,32 @@ class DbManage(object): #('phases', 'publish', 'false') ] for section, key, value in ui_config: - ui_conf = RhodeCodeUi() + ui_conf = Ui() setattr(ui_conf, 'ui_section', section) setattr(ui_conf, 'ui_key', key) setattr(ui_conf, 'ui_value', value) self.sa.add(ui_conf) settings = [ - ('realm', 'RhodeCode authentication', unicode), - ('title', 'RhodeCode', unicode), - ('ga_code', '', unicode), - ('show_public_icon', True, bool), - ('show_private_icon', True, bool), - ('stylify_metatags', False, bool), - ('dashboard_items', 100, int), - ('show_version', True, bool) + ('realm', 'Kallithea', 'unicode'), + ('title', '', 'unicode'), + ('ga_code', '', 'unicode'), + ('show_public_icon', True, 'bool'), + ('show_private_icon', True, 'bool'), + ('stylify_metatags', False, 'bool'), + ('dashboard_items', 100, 'int'), + ('admin_grid_items', 25, 'int'), + ('show_version', True, 'bool'), + ('use_gravatar', True, 'bool'), + ('gravatar_url', User.DEFAULT_GRAVATAR_URL, 'unicode'), + ('clone_uri_tmpl', Repository.DEFAULT_CLONE_URI, 'unicode'), + ('update_url', Setting.DEFAULT_UPDATE_URL, 'unicode'), ] for key, val, type_ in settings: - sett = RhodeCodeSetting(key, val) + sett = Setting(key, val, type_) self.sa.add(sett) - self.create_ldap_options() + self.create_auth_plugin_options() self.create_default_options() log.info('created ui config') @@ -690,15 +540,16 @@ class DbManage(object): def create_user(self, username, password, email='', admin=False): log.info('creating user %s' % username) UserModel().create_or_update(username, password, email, - firstname='RhodeCode', lastname='Admin', - active=True, admin=admin) + firstname='Kallithea', lastname='Admin', + active=True, admin=admin, + extern_type=EXTERN_TYPE_INTERNAL) def create_default_user(self): log.info('creating default user') # create default user for handling default permissions. user = UserModel().create_or_update(username=User.DEFAULT_USER, password=str(uuid.uuid1())[:20], - email='anonymous@rhodecode.org', + email='anonymous@kallithea-scm.org', firstname='Anonymous', lastname='User') # based on configuration options activate/deactive this user which diff --git a/rhodecode/lib/dbmigrate/__init__.py b/kallithea/lib/dbmigrate/__init__.py rename from rhodecode/lib/dbmigrate/__init__.py rename to kallithea/lib/dbmigrate/__init__.py --- a/rhodecode/lib/dbmigrate/__init__.py +++ b/kallithea/lib/dbmigrate/__init__.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.dbmigrate.__init__ - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Database migration modules - - :created_on: Dec 11, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,13 +11,26 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.dbmigrate.__init__ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Database migration modules + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Dec 11, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import logging from sqlalchemy import engine_from_config -from rhodecode.lib.utils import BasePasterCommand, Command, add_cache -from rhodecode.lib.db_manage import DbManage +from kallithea.lib.utils import BasePasterCommand, Command, add_cache +from kallithea.lib.db_manage import DbManage log = logging.getLogger(__name__) @@ -42,20 +44,18 @@ class UpgradeDb(BasePasterCommand): usage = "CONFIG_FILE" summary = "Upgrades current db to newer version" - group_name = "RhodeCode" + group_name = "Kallithea" parser = Command.standard_parser(verbose=True) def command(self): from pylons import config - add_cache(config) db_uri = config['sqlalchemy.db1.url'] - dbmanage = DbManage(log_sql=True, dbconf=db_uri, - root=config['here'], tests=False) - + root=config['here'], tests=False, + cli_args=self.options.__dict__) dbmanage.upgrade() def update_parser(self): @@ -64,3 +64,14 @@ class UpgradeDb(BasePasterCommand): dest='just_sql', help="Prints upgrade sql for further investigation", default=False) + + self.parser.add_option('--force-yes', + action='store_true', + dest='force_ask', + default=None, + help='Force yes to every question') + self.parser.add_option('--force-no', + action='store_false', + dest='force_ask', + default=None, + help='Force no to every question') diff --git a/rhodecode/lib/dbmigrate/migrate.cfg b/kallithea/lib/dbmigrate/migrate.cfg rename from rhodecode/lib/dbmigrate/migrate.cfg rename to kallithea/lib/dbmigrate/migrate.cfg --- a/rhodecode/lib/dbmigrate/migrate.cfg +++ b/kallithea/lib/dbmigrate/migrate.cfg @@ -1,7 +1,7 @@ [db_settings] # Used to identify which repository this database is versioned under. # You can use the name of your project. -repository_id=rhodecode_db_migrations +repository_id=kallithea_db_migrations # The name of the database table used to track the schema version. # This name shouldn't already be used by your project. diff --git a/rhodecode/lib/dbmigrate/migrate/__init__.py b/kallithea/lib/dbmigrate/migrate/__init__.py rename from rhodecode/lib/dbmigrate/migrate/__init__.py rename to kallithea/lib/dbmigrate/migrate/__init__.py --- a/rhodecode/lib/dbmigrate/migrate/__init__.py +++ b/kallithea/lib/dbmigrate/migrate/__init__.py @@ -5,7 +5,7 @@ using Python. """ -from rhodecode.lib.dbmigrate.migrate.versioning import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate.versioning import * +from kallithea.lib.dbmigrate.migrate.changeset import * __version__ = '0.7.3.dev' diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/__init__.py b/kallithea/lib/dbmigrate/migrate/changeset/__init__.py rename from rhodecode/lib/dbmigrate/migrate/changeset/__init__.py rename to kallithea/lib/dbmigrate/migrate/changeset/__init__.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/__init__.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/__init__.py @@ -20,8 +20,8 @@ SQLA_07 = _sa_version >= (0, 7) del re del _sa_version -from rhodecode.lib.dbmigrate.migrate.changeset.schema import * -from rhodecode.lib.dbmigrate.migrate.changeset.constraint import * +from kallithea.lib.dbmigrate.migrate.changeset.schema import * +from kallithea.lib.dbmigrate.migrate.changeset.constraint import * sqlalchemy.schema.Table.__bases__ += (ChangesetTable,) sqlalchemy.schema.Column.__bases__ += (ChangesetColumn,) diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/ansisql.py b/kallithea/lib/dbmigrate/migrate/changeset/ansisql.py rename from rhodecode/lib/dbmigrate/migrate/changeset/ansisql.py rename to kallithea/lib/dbmigrate/migrate/changeset/ansisql.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/ansisql.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/ansisql.py @@ -16,8 +16,8 @@ from sqlalchemy.schema import (ForeignKe UniqueConstraint, Index) -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.changeset import constraint +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.changeset import constraint from sqlalchemy.schema import AddConstraint, DropConstraint from sqlalchemy.sql.compiler import DDLCompiler diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/constraint.py b/kallithea/lib/dbmigrate/migrate/changeset/constraint.py rename from rhodecode/lib/dbmigrate/migrate/changeset/constraint.py rename to kallithea/lib/dbmigrate/migrate/changeset/constraint.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/constraint.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/constraint.py @@ -3,7 +3,7 @@ """ from sqlalchemy import schema -from rhodecode.lib.dbmigrate.migrate.exceptions import * +from kallithea.lib.dbmigrate.migrate.exceptions import * class ConstraintChangeset(object): @@ -27,7 +27,7 @@ class ConstraintChangeset(object): def __do_imports(self, visitor_name, *a, **kw): engine = kw.pop('engine', self.table.bind) - from rhodecode.lib.dbmigrate.migrate.changeset.databases.visitor import (get_engine_visitor, + from kallithea.lib.dbmigrate.migrate.changeset.databases.visitor import (get_engine_visitor, run_single_visitor) visitorcallable = get_engine_visitor(engine, visitor_name) run_single_visitor(engine, visitorcallable, self, *a, **kw) diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/databases/__init__.py b/kallithea/lib/dbmigrate/migrate/changeset/databases/__init__.py rename from rhodecode/lib/dbmigrate/migrate/changeset/databases/__init__.py rename to kallithea/lib/dbmigrate/migrate/changeset/databases/__init__.py diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/databases/firebird.py b/kallithea/lib/dbmigrate/migrate/changeset/databases/firebird.py rename from rhodecode/lib/dbmigrate/migrate/changeset/databases/firebird.py rename to kallithea/lib/dbmigrate/migrate/changeset/databases/firebird.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/databases/firebird.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/databases/firebird.py @@ -3,8 +3,8 @@ """ from sqlalchemy.databases import firebird as sa_base from sqlalchemy.schema import PrimaryKeyConstraint -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.changeset import ansisql +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.changeset import ansisql FBSchemaGenerator = sa_base.FBDDLCompiler diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/databases/mysql.py b/kallithea/lib/dbmigrate/migrate/changeset/databases/mysql.py rename from rhodecode/lib/dbmigrate/migrate/changeset/databases/mysql.py rename to kallithea/lib/dbmigrate/migrate/changeset/databases/mysql.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/databases/mysql.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/databases/mysql.py @@ -5,8 +5,8 @@ from sqlalchemy.databases import mysql as sa_base from sqlalchemy import types as sqltypes -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.changeset import ansisql +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.changeset import ansisql MySQLSchemaGenerator = sa_base.MySQLDDLCompiler diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/databases/oracle.py b/kallithea/lib/dbmigrate/migrate/changeset/databases/oracle.py rename from rhodecode/lib/dbmigrate/migrate/changeset/databases/oracle.py rename to kallithea/lib/dbmigrate/migrate/changeset/databases/oracle.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/databases/oracle.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/databases/oracle.py @@ -4,8 +4,8 @@ import sqlalchemy as sa from sqlalchemy.databases import oracle as sa_base -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06 +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06 if not SQLA_06: diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/databases/postgres.py b/kallithea/lib/dbmigrate/migrate/changeset/databases/postgres.py rename from rhodecode/lib/dbmigrate/migrate/changeset/databases/postgres.py rename to kallithea/lib/dbmigrate/migrate/changeset/databases/postgres.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/databases/postgres.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/databases/postgres.py @@ -3,7 +3,7 @@ .. _`PostgreSQL`: http://www.postgresql.org/ """ -from rhodecode.lib.dbmigrate.migrate.changeset import ansisql +from kallithea.lib.dbmigrate.migrate.changeset import ansisql from sqlalchemy.databases import postgresql as sa_base diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/databases/sqlite.py b/kallithea/lib/dbmigrate/migrate/changeset/databases/sqlite.py rename from rhodecode/lib/dbmigrate/migrate/changeset/databases/sqlite.py rename to kallithea/lib/dbmigrate/migrate/changeset/databases/sqlite.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/databases/sqlite.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/databases/sqlite.py @@ -8,8 +8,8 @@ from copy import copy from sqlalchemy.databases import sqlite as sa_base -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06 +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06 SQLiteSchemaGenerator = sa_base.SQLiteDDLCompiler diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/databases/visitor.py b/kallithea/lib/dbmigrate/migrate/changeset/databases/visitor.py rename from rhodecode/lib/dbmigrate/migrate/changeset/databases/visitor.py rename to kallithea/lib/dbmigrate/migrate/changeset/databases/visitor.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/databases/visitor.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/databases/visitor.py @@ -3,8 +3,8 @@ """ import sqlalchemy as sa -from rhodecode.lib.dbmigrate.migrate.changeset import ansisql -from rhodecode.lib.dbmigrate.migrate.changeset.databases import (sqlite, +from kallithea.lib.dbmigrate.migrate.changeset import ansisql +from kallithea.lib.dbmigrate.migrate.changeset.databases import (sqlite, postgres, mysql, oracle, diff --git a/rhodecode/lib/dbmigrate/migrate/changeset/schema.py b/kallithea/lib/dbmigrate/migrate/changeset/schema.py rename from rhodecode/lib/dbmigrate/migrate/changeset/schema.py rename to kallithea/lib/dbmigrate/migrate/changeset/schema.py --- a/rhodecode/lib/dbmigrate/migrate/changeset/schema.py +++ b/kallithea/lib/dbmigrate/migrate/changeset/schema.py @@ -10,9 +10,9 @@ import sqlalchemy from sqlalchemy.schema import ForeignKeyConstraint from sqlalchemy.schema import UniqueConstraint -from rhodecode.lib.dbmigrate.migrate.exceptions import * -from rhodecode.lib.dbmigrate.migrate.changeset import SQLA_06, SQLA_07 -from rhodecode.lib.dbmigrate.migrate.changeset.databases.visitor import (get_engine_visitor, +from kallithea.lib.dbmigrate.migrate.exceptions import * +from kallithea.lib.dbmigrate.migrate.changeset import SQLA_06, SQLA_07 +from kallithea.lib.dbmigrate.migrate.changeset.databases.visitor import (get_engine_visitor, run_single_visitor) diff --git a/rhodecode/lib/dbmigrate/migrate/exceptions.py b/kallithea/lib/dbmigrate/migrate/exceptions.py rename from rhodecode/lib/dbmigrate/migrate/exceptions.py rename to kallithea/lib/dbmigrate/migrate/exceptions.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/__init__.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/api.py b/kallithea/lib/dbmigrate/migrate/versioning/api.py rename from rhodecode/lib/dbmigrate/migrate/versioning/api.py rename to kallithea/lib/dbmigrate/migrate/versioning/api.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/api.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/api.py @@ -29,10 +29,10 @@ import sys import inspect import logging -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.versioning import repository, schema, version, \ +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.versioning import repository, schema, version, \ script as script_ # command name conflict -from rhodecode.lib.dbmigrate.migrate.versioning.util import catch_known_errors, with_engine +from kallithea.lib.dbmigrate.migrate.versioning.util import catch_known_errors, with_engine log = logging.getLogger(__name__) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/cfgparse.py b/kallithea/lib/dbmigrate/migrate/versioning/cfgparse.py rename from rhodecode/lib/dbmigrate/migrate/versioning/cfgparse.py rename to kallithea/lib/dbmigrate/migrate/versioning/cfgparse.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/cfgparse.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/cfgparse.py @@ -4,8 +4,8 @@ from ConfigParser import ConfigParser -from rhodecode.lib.dbmigrate.migrate.versioning.config import * -from rhodecode.lib.dbmigrate.migrate.versioning import pathed +from kallithea.lib.dbmigrate.migrate.versioning.config import * +from kallithea.lib.dbmigrate.migrate.versioning import pathed class Parser(ConfigParser): diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/config.py b/kallithea/lib/dbmigrate/migrate/versioning/config.py rename from rhodecode/lib/dbmigrate/migrate/versioning/config.py rename to kallithea/lib/dbmigrate/migrate/versioning/config.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/genmodel.py b/kallithea/lib/dbmigrate/migrate/versioning/genmodel.py rename from rhodecode/lib/dbmigrate/migrate/versioning/genmodel.py rename to kallithea/lib/dbmigrate/migrate/versioning/genmodel.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/genmodel.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/genmodel.py @@ -11,8 +11,8 @@ import logging import sqlalchemy -from rhodecode.lib.dbmigrate import migrate -from rhodecode.lib.dbmigrate.migrate import changeset +from kallithea.lib.dbmigrate import migrate +from kallithea.lib.dbmigrate.migrate import changeset log = logging.getLogger(__name__) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/migrate_repository.py b/kallithea/lib/dbmigrate/migrate/versioning/migrate_repository.py rename from rhodecode/lib/dbmigrate/migrate/versioning/migrate_repository.py rename to kallithea/lib/dbmigrate/migrate/versioning/migrate_repository.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/pathed.py b/kallithea/lib/dbmigrate/migrate/versioning/pathed.py rename from rhodecode/lib/dbmigrate/migrate/versioning/pathed.py rename to kallithea/lib/dbmigrate/migrate/versioning/pathed.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/pathed.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/pathed.py @@ -6,9 +6,9 @@ import os import shutil import logging -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.versioning.config import * -from rhodecode.lib.dbmigrate.migrate.versioning.util import KeyedInstance +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.versioning.config import * +from kallithea.lib.dbmigrate.migrate.versioning.util import KeyedInstance log = logging.getLogger(__name__) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/repository.py b/kallithea/lib/dbmigrate/migrate/versioning/repository.py rename from rhodecode/lib/dbmigrate/migrate/versioning/repository.py rename to kallithea/lib/dbmigrate/migrate/versioning/repository.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/repository.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/repository.py @@ -9,10 +9,11 @@ import logging from pkg_resources import resource_filename from tempita import Template as TempitaTemplate -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.versioning import version, pathed, cfgparse -from rhodecode.lib.dbmigrate.migrate.versioning.template import Template -from rhodecode.lib.dbmigrate.migrate.versioning.config import * +import kallithea +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.versioning import version, pathed, cfgparse +from kallithea.lib.dbmigrate.migrate.versioning.template import Template +from kallithea.lib.dbmigrate.migrate.versioning.config import * log = logging.getLogger(__name__) @@ -175,7 +176,11 @@ class Repository(pathed.Pathed): @property def id(self): """Returns repository id specified in config""" - return self.config.get('db_settings', 'repository_id') + # Adjust the value read from kallithea/lib/dbmigrate/migrate.cfg, normally "kallithea_db_migrations" + s = self.config.get('db_settings', 'repository_id') + if s == "kallithea_db_migrations": + s = kallithea.DB_MIGRATIONS + return s @property def use_timestamp_numbering(self): diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/schema.py b/kallithea/lib/dbmigrate/migrate/versioning/schema.py rename from rhodecode/lib/dbmigrate/migrate/versioning/schema.py rename to kallithea/lib/dbmigrate/migrate/versioning/schema.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/schema.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/schema.py @@ -10,12 +10,12 @@ from sqlalchemy.sql import and_ from sqlalchemy import exc as sa_exceptions from sqlalchemy.sql import bindparam -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.changeset import SQLA_07 -from rhodecode.lib.dbmigrate.migrate.versioning import genmodel, schemadiff -from rhodecode.lib.dbmigrate.migrate.versioning.repository import Repository -from rhodecode.lib.dbmigrate.migrate.versioning.util import load_model -from rhodecode.lib.dbmigrate.migrate.versioning.version import VerNum +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.changeset import SQLA_07 +from kallithea.lib.dbmigrate.migrate.versioning import genmodel, schemadiff +from kallithea.lib.dbmigrate.migrate.versioning.repository import Repository +from kallithea.lib.dbmigrate.migrate.versioning.util import load_model +from kallithea.lib.dbmigrate.migrate.versioning.version import VerNum log = logging.getLogger(__name__) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/schemadiff.py b/kallithea/lib/dbmigrate/migrate/versioning/schemadiff.py rename from rhodecode/lib/dbmigrate/migrate/versioning/schemadiff.py rename to kallithea/lib/dbmigrate/migrate/versioning/schemadiff.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/schemadiff.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/schemadiff.py @@ -5,7 +5,7 @@ import logging import sqlalchemy -from rhodecode.lib.dbmigrate.migrate.changeset import SQLA_06 +from kallithea.lib.dbmigrate.migrate.changeset import SQLA_06 from sqlalchemy.types import Float log = logging.getLogger(__name__) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/script/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/script/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/script/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/script/__init__.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/script/__init__.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/script/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from rhodecode.lib.dbmigrate.migrate.versioning.script.base import BaseScript -from rhodecode.lib.dbmigrate.migrate.versioning.script.py import PythonScript -from rhodecode.lib.dbmigrate.migrate.versioning.script.sql import SqlScript +from kallithea.lib.dbmigrate.migrate.versioning.script.base import BaseScript +from kallithea.lib.dbmigrate.migrate.versioning.script.py import PythonScript +from kallithea.lib.dbmigrate.migrate.versioning.script.sql import SqlScript diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/script/base.py b/kallithea/lib/dbmigrate/migrate/versioning/script/base.py rename from rhodecode/lib/dbmigrate/migrate/versioning/script/base.py rename to kallithea/lib/dbmigrate/migrate/versioning/script/base.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/script/base.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/script/base.py @@ -2,9 +2,9 @@ # -*- coding: utf-8 -*- import logging -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.versioning.config import operations -from rhodecode.lib.dbmigrate.migrate.versioning import pathed +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.versioning.config import operations +from kallithea.lib.dbmigrate.migrate.versioning import pathed log = logging.getLogger(__name__) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/script/py.py b/kallithea/lib/dbmigrate/migrate/versioning/script/py.py rename from rhodecode/lib/dbmigrate/migrate/versioning/script/py.py rename to kallithea/lib/dbmigrate/migrate/versioning/script/py.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/script/py.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/script/py.py @@ -7,13 +7,13 @@ import logging import inspect from StringIO import StringIO -from rhodecode.lib.dbmigrate import migrate -from rhodecode.lib.dbmigrate.migrate.versioning import genmodel, schemadiff -from rhodecode.lib.dbmigrate.migrate.versioning.config import operations -from rhodecode.lib.dbmigrate.migrate.versioning.template import Template -from rhodecode.lib.dbmigrate.migrate.versioning.script import base -from rhodecode.lib.dbmigrate.migrate.versioning.util import import_path, load_model, with_engine -from rhodecode.lib.dbmigrate.migrate.exceptions import MigrateDeprecationWarning, InvalidScriptError, ScriptError +from kallithea.lib.dbmigrate import migrate +from kallithea.lib.dbmigrate.migrate.versioning import genmodel, schemadiff +from kallithea.lib.dbmigrate.migrate.versioning.config import operations +from kallithea.lib.dbmigrate.migrate.versioning.template import Template +from kallithea.lib.dbmigrate.migrate.versioning.script import base +from kallithea.lib.dbmigrate.migrate.versioning.util import import_path, load_model, with_engine +from kallithea.lib.dbmigrate.migrate.exceptions import MigrateDeprecationWarning, InvalidScriptError, ScriptError log = logging.getLogger(__name__) __all__ = ['PythonScript'] @@ -53,7 +53,7 @@ class PythonScript(base.BaseScript): if isinstance(repository, basestring): # oh dear, an import cycle! - from rhodecode.lib.dbmigrate.migrate.versioning.repository import Repository + from kallithea.lib.dbmigrate.migrate.versioning.repository import Repository repository = Repository(repository) oldmodel = load_model(oldmodel) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/script/sql.py b/kallithea/lib/dbmigrate/migrate/versioning/script/sql.py rename from rhodecode/lib/dbmigrate/migrate/versioning/script/sql.py rename to kallithea/lib/dbmigrate/migrate/versioning/script/sql.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/script/sql.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/script/sql.py @@ -3,8 +3,8 @@ import logging import shutil -from rhodecode.lib.dbmigrate.migrate.versioning.script import base -from rhodecode.lib.dbmigrate.migrate.versioning.template import Template +from kallithea.lib.dbmigrate.migrate.versioning.script import base +from kallithea.lib.dbmigrate.migrate.versioning.template import Template log = logging.getLogger(__name__) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/shell.py b/kallithea/lib/dbmigrate/migrate/versioning/shell.py rename from rhodecode/lib/dbmigrate/migrate/versioning/shell.py rename to kallithea/lib/dbmigrate/migrate/versioning/shell.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/shell.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/shell.py @@ -8,10 +8,10 @@ import inspect import logging from optparse import OptionParser, BadOptionError -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.versioning import api -from rhodecode.lib.dbmigrate.migrate.versioning.config import * -from rhodecode.lib.dbmigrate.migrate.versioning.util import asbool +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.versioning import api +from kallithea.lib.dbmigrate.migrate.versioning.config import * +from kallithea.lib.dbmigrate.migrate.versioning.util import asbool alias = dict( diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/template.py b/kallithea/lib/dbmigrate/migrate/versioning/template.py rename from rhodecode/lib/dbmigrate/migrate/versioning/template.py rename to kallithea/lib/dbmigrate/migrate/versioning/template.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/template.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/template.py @@ -7,8 +7,8 @@ import sys from pkg_resources import resource_filename -from rhodecode.lib.dbmigrate.migrate.versioning.config import * -from rhodecode.lib.dbmigrate.migrate.versioning import pathed +from kallithea.lib.dbmigrate.migrate.versioning.config import * +from kallithea.lib.dbmigrate.migrate.versioning import pathed class Collection(pathed.Pathed): @@ -34,10 +34,10 @@ class SQLScriptCollection(Collection): class Template(pathed.Pathed): """Finds the paths/packages of various Migrate templates. - :param path: Templates are loaded from rhodecode.lib.dbmigrate.migrate package + :param path: Templates are loaded from kallithea.lib.dbmigrate.migrate package if `path` is not provided. """ - pkg = 'rhodecode.lib.dbmigrate.migrate.versioning.templates' + pkg = 'kallithea.lib.dbmigrate.migrate.versioning.templates' _manage = 'manage.py_tmpl' def __new__(cls, path=None): diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/templates/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/templates/__init__.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/manage.py_tmpl b/kallithea/lib/dbmigrate/migrate/versioning/templates/manage.py_tmpl rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/manage.py_tmpl rename to kallithea/lib/dbmigrate/migrate/versioning/templates/manage.py_tmpl diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/manage/default.py_tmpl b/kallithea/lib/dbmigrate/migrate/versioning/templates/manage/default.py_tmpl rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/manage/default.py_tmpl rename to kallithea/lib/dbmigrate/migrate/versioning/templates/manage/default.py_tmpl diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/manage/pylons.py_tmpl b/kallithea/lib/dbmigrate/migrate/versioning/templates/manage/pylons.py_tmpl rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/manage/pylons.py_tmpl rename to kallithea/lib/dbmigrate/migrate/versioning/templates/manage/pylons.py_tmpl diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/templates/repository/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/templates/repository/__init__.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/README b/kallithea/lib/dbmigrate/migrate/versioning/templates/repository/default/README rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/README rename to kallithea/lib/dbmigrate/migrate/versioning/templates/repository/default/README diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/templates/repository/default/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/templates/repository/default/__init__.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/migrate.cfg b/kallithea/lib/dbmigrate/migrate/versioning/templates/repository/default/migrate.cfg rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/migrate.cfg rename to kallithea/lib/dbmigrate/migrate/versioning/templates/repository/default/migrate.cfg diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/versions/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/templates/repository/default/versions/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/versions/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/templates/repository/default/versions/__init__.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/pylons/README b/kallithea/lib/dbmigrate/migrate/versioning/templates/repository/pylons/README rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/pylons/README rename to kallithea/lib/dbmigrate/migrate/versioning/templates/repository/pylons/README diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/pylons/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/templates/repository/pylons/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/pylons/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/templates/repository/pylons/__init__.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/pylons/migrate.cfg b/kallithea/lib/dbmigrate/migrate/versioning/templates/repository/pylons/migrate.cfg rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/pylons/migrate.cfg rename to kallithea/lib/dbmigrate/migrate/versioning/templates/repository/pylons/migrate.cfg diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/pylons/versions/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/templates/repository/pylons/versions/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/pylons/versions/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/templates/repository/pylons/versions/__init__.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/script/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/templates/script/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/script/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/templates/script/__init__.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/script/default.py_tmpl b/kallithea/lib/dbmigrate/migrate/versioning/templates/script/default.py_tmpl rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/script/default.py_tmpl rename to kallithea/lib/dbmigrate/migrate/versioning/templates/script/default.py_tmpl diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/script/pylons.py_tmpl b/kallithea/lib/dbmigrate/migrate/versioning/templates/script/pylons.py_tmpl rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/script/pylons.py_tmpl rename to kallithea/lib/dbmigrate/migrate/versioning/templates/script/pylons.py_tmpl diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/sql_script/default.py_tmpl b/kallithea/lib/dbmigrate/migrate/versioning/templates/sql_script/default.py_tmpl rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/sql_script/default.py_tmpl rename to kallithea/lib/dbmigrate/migrate/versioning/templates/sql_script/default.py_tmpl diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/templates/sql_script/pylons.py_tmpl b/kallithea/lib/dbmigrate/migrate/versioning/templates/sql_script/pylons.py_tmpl rename from rhodecode/lib/dbmigrate/migrate/versioning/templates/sql_script/pylons.py_tmpl rename to kallithea/lib/dbmigrate/migrate/versioning/templates/sql_script/pylons.py_tmpl diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py b/kallithea/lib/dbmigrate/migrate/versioning/util/__init__.py rename from rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py rename to kallithea/lib/dbmigrate/migrate/versioning/util/__init__.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/util/__init__.py @@ -11,9 +11,9 @@ from sqlalchemy import create_engine from sqlalchemy.engine import Engine from sqlalchemy.pool import StaticPool -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.versioning.util.keyedinstance import KeyedInstance -from rhodecode.lib.dbmigrate.migrate.versioning.util.importpath import import_path +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.versioning.util.keyedinstance import KeyedInstance +from kallithea.lib.dbmigrate.migrate.versioning.util.importpath import import_path log = logging.getLogger(__name__) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/util/importpath.py b/kallithea/lib/dbmigrate/migrate/versioning/util/importpath.py rename from rhodecode/lib/dbmigrate/migrate/versioning/util/importpath.py rename to kallithea/lib/dbmigrate/migrate/versioning/util/importpath.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/util/keyedinstance.py b/kallithea/lib/dbmigrate/migrate/versioning/util/keyedinstance.py rename from rhodecode/lib/dbmigrate/migrate/versioning/util/keyedinstance.py rename to kallithea/lib/dbmigrate/migrate/versioning/util/keyedinstance.py diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/version.py b/kallithea/lib/dbmigrate/migrate/versioning/version.py rename from rhodecode/lib/dbmigrate/migrate/versioning/version.py rename to kallithea/lib/dbmigrate/migrate/versioning/version.py --- a/rhodecode/lib/dbmigrate/migrate/versioning/version.py +++ b/kallithea/lib/dbmigrate/migrate/versioning/version.py @@ -6,8 +6,8 @@ import re import shutil import logging -from rhodecode.lib.dbmigrate.migrate import exceptions -from rhodecode.lib.dbmigrate.migrate.versioning import pathed, script +from kallithea.lib.dbmigrate.migrate import exceptions +from kallithea.lib.dbmigrate.migrate.versioning import pathed, script from datetime import datetime diff --git a/rhodecode/lib/dbmigrate/schema/__init__.py b/kallithea/lib/dbmigrate/schema/__init__.py rename from rhodecode/lib/dbmigrate/schema/__init__.py rename to kallithea/lib/dbmigrate/schema/__init__.py --- a/rhodecode/lib/dbmigrate/schema/__init__.py +++ b/kallithea/lib/dbmigrate/schema/__init__.py @@ -1,14 +1,26 @@ # -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . """ - rhodecode.lib.dbmigrate.schema - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +kallithea.lib.dbmigrate.schema +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Schemas for migrations - +Schemas for migrations - :created_on: Nov 1, 2011 - :author: marcink - :copyright: (C) 2009-2010 Marcin Kuzminski - :license: , see LICENSE_FILE for more details. +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Nov 1, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. """ diff --git a/rhodecode/lib/dbmigrate/schema/db_1_1_0.py b/kallithea/lib/dbmigrate/schema/db_1_1_0.py rename from rhodecode/lib/dbmigrate/schema/db_1_1_0.py rename to kallithea/lib/dbmigrate/schema/db_1_1_0.py --- a/rhodecode/lib/dbmigrate/schema/db_1_1_0.py +++ b/kallithea/lib/dbmigrate/schema/db_1_1_0.py @@ -2,7 +2,7 @@ from sqlalchemy import * from sqlalchemy.exc import DatabaseError from sqlalchemy.orm import relation, backref, class_mapper from sqlalchemy.orm.session import Session -from rhodecode.model.meta import Base +from kallithea.model.meta import Base class BaseModel(object): """Base Model for all classess diff --git a/rhodecode/lib/dbmigrate/schema/db_1_2_0.py b/kallithea/lib/dbmigrate/schema/db_1_2_0.py rename from rhodecode/lib/dbmigrate/schema/db_1_2_0.py rename to kallithea/lib/dbmigrate/schema/db_1_2_0.py --- a/rhodecode/lib/dbmigrate/schema/db_1_2_0.py +++ b/kallithea/lib/dbmigrate/schema/db_1_2_0.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.db_1_2_0 - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Database Models for RhodeCode <=1.2.X - - :created_on: Apr 08, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.db_1_2_0 +~~~~~~~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea <=1.2.X + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import os import logging @@ -34,19 +36,20 @@ from sqlalchemy.ext.hybrid import hybrid from sqlalchemy.orm import relationship, joinedload, class_mapper, validates from beaker.cache import cache_region, region_invalidate -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ generate_api_key, safe_unicode -from rhodecode.lib.exceptions import UserGroupsAssignedException -from rhodecode.lib.compat import json +from kallithea.lib.exceptions import UserGroupsAssignedException +from kallithea.lib.compat import json -from rhodecode.model.meta import Base, Session -from rhodecode.lib.caching_query import FromCache +from kallithea.model.meta import Base, Session +from kallithea.lib.caching_query import FromCache +from kallithea import DB_PREFIX log = logging.getLogger(__name__) @@ -139,8 +142,8 @@ class BaseModel(object): Session.commit() -class RhodeCodeSetting(Base, BaseModel): - __tablename__ = 'rhodecode_settings' +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True}) app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) @@ -194,7 +197,7 @@ class RhodeCodeSetting(Base, BaseModel): raise Exception('Could not get application settings !') settings = {} for each in ret: - settings['rhodecode_' + each.app_settings_name] = \ + settings[each.app_settings_name] = \ each.app_settings_value return settings @@ -210,8 +213,8 @@ class RhodeCodeSetting(Base, BaseModel): return fd -class RhodeCodeUi(Base, BaseModel): - __tablename__ = 'rhodecode_ui' +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True}) HOOK_UPDATE = 'changegroup.update' @@ -324,7 +327,7 @@ class User(Base, BaseModel): @classmethod def create(cls, form_data): - from rhodecode.lib.auth import get_crypt_password + from kallithea.lib.auth import get_crypt_password try: new_user = cls() @@ -539,7 +542,7 @@ class Repository(Base, BaseModel): :param cls: """ - q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == + q = Session.query(Ui).filter(Ui.ui_key == cls.url_sep()) q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -575,7 +578,7 @@ class Repository(Base, BaseModel): Returns base full path for that repository means where it actually exists on a filesystem """ - q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == + q = Session.query(Ui).filter(Ui.ui_key == Repository.url_sep()) q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -613,7 +616,7 @@ class Repository(Base, BaseModel): baseui._tcfg = config.config() - ret = RhodeCodeUi.query()\ + ret = Ui.query()\ .options(FromCache("sql_cache_short", "repository_repo_ui")).all() hg_ui = ret @@ -633,7 +636,7 @@ class Repository(Base, BaseModel): :param cls: :param repo_name: """ - from rhodecode.lib.utils import is_valid_repo + from kallithea.lib.utils import is_valid_repo return is_valid_repo(repo_name, cls.base_path()) @@ -903,7 +906,7 @@ class UserToPerm(Base, BaseModel): raise Exception('perm needs to be an instance of Permission class') try: - cls.query().filter(cls.user_id == user_id)\ + cls.query().filter(cls.user_id == user_id) \ .filter(cls.permission == perm).delete() Session.commit() except: @@ -966,7 +969,7 @@ class UserGroupToPerm(Base, BaseModel): raise Exception('perm needs to be an instance of Permission class') try: - cls.query().filter(cls.users_group_id == users_group_id)\ + cls.query().filter(cls.users_group_id == users_group_id) \ .filter(cls.permission == perm).delete() Session.commit() except: diff --git a/rhodecode/lib/dbmigrate/schema/db_1_3_0.py b/kallithea/lib/dbmigrate/schema/db_1_3_0.py rename from rhodecode/lib/dbmigrate/schema/db_1_3_0.py rename to kallithea/lib/dbmigrate/schema/db_1_3_0.py --- a/rhodecode/lib/dbmigrate/schema/db_1_3_0.py +++ b/kallithea/lib/dbmigrate/schema/db_1_3_0.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.db_1_3_0 - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Database Models for RhodeCode <=1.3.X - - :created_on: Apr 08, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.db_1_3_0 +~~~~~~~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea <=1.3.X + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" + import os import logging @@ -34,19 +38,20 @@ from sqlalchemy.ext.hybrid import hybrid from sqlalchemy.orm import relationship, joinedload, class_mapper, validates from beaker.cache import cache_region, region_invalidate -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ safe_unicode -from rhodecode.lib.compat import json -from rhodecode.lib.caching_query import FromCache +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache -from rhodecode.model.meta import Base, Session +from kallithea.model.meta import Base, Session import hashlib +from kallithea import DB_PREFIX log = logging.getLogger(__name__) @@ -152,8 +157,8 @@ class BaseModel(object): return safe_str(self.__unicode__()) return '' % (self.__class__.__name__) -class RhodeCodeSetting(Base, BaseModel): - __tablename__ = 'rhodecode_settings' +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' __table_args__ = ( UniqueConstraint('app_settings_name'), {'extend_existing': True, 'mysql_engine':'InnoDB', @@ -211,7 +216,7 @@ class RhodeCodeSetting(Base, BaseModel): raise Exception('Could not get application settings !') settings = {} for each in ret: - settings['rhodecode_' + each.app_settings_name] = \ + settings[each.app_settings_name] = \ each.app_settings_value return settings @@ -227,8 +232,8 @@ class RhodeCodeSetting(Base, BaseModel): return fd -class RhodeCodeUi(Base, BaseModel): - __tablename__ = 'rhodecode_ui' +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' __table_args__ = ( UniqueConstraint('ui_key'), {'extend_existing': True, 'mysql_engine':'InnoDB', @@ -544,8 +549,8 @@ class Repository(Base, BaseModel): :param cls: """ - q = Session.query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == cls.url_sep()) + q = Session.query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -580,7 +585,7 @@ class Repository(Base, BaseModel): Returns base full path for that repository means where it actually exists on a filesystem """ - q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == + q = Session.query(Ui).filter(Ui.ui_key == Repository.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -617,7 +622,7 @@ class Repository(Base, BaseModel): baseui._ucfg = config.config() baseui._tcfg = config.config() - ret = RhodeCodeUi.query()\ + ret = Ui.query()\ .options(FromCache("sql_cache_short", "repository_repo_ui")).all() hg_ui = ret @@ -637,7 +642,7 @@ class Repository(Base, BaseModel): :param cls: :param repo_name: """ - from rhodecode.lib.utils import is_valid_repo + from kallithea.lib.utils import is_valid_repo return is_valid_repo(repo_name, cls.base_path()) @@ -1099,9 +1104,9 @@ class CacheInvalidation(Base, BaseModel) :param key: """ - import rhodecode + import kallithea prefix = '' - iid = rhodecode.CONFIG.get('instance_id') + iid = kallithea.CONFIG.get('instance_id') if iid: prefix = iid return "%s%s" % (prefix, key), prefix, key.rstrip('_README') @@ -1256,7 +1261,7 @@ class Notification(Base, BaseModel): @property def description(self): - from rhodecode.model.notification import NotificationModel + from kallithea.model.notification import NotificationModel return NotificationModel().make_description(self) diff --git a/rhodecode/lib/dbmigrate/schema/db_1_4_0.py b/kallithea/lib/dbmigrate/schema/db_1_4_0.py rename from rhodecode/lib/dbmigrate/schema/db_1_4_0.py rename to kallithea/lib/dbmigrate/schema/db_1_4_0.py --- a/rhodecode/lib/dbmigrate/schema/db_1_4_0.py +++ b/kallithea/lib/dbmigrate/schema/db_1_4_0.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.db_1_4_0 - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Database Models for RhodeCode <=1.4.X - - :created_on: Apr 08, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.db_1_4_0 +~~~~~~~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea <=1.4.X + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import os import logging @@ -40,17 +43,19 @@ from webob.exc import HTTPNotFound from pylons.i18n.translation import lazy_ugettext as _ -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ safe_unicode, remove_suffix -from rhodecode.lib.compat import json -from rhodecode.lib.caching_query import FromCache +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache -from rhodecode.model.meta import Base, Session +from kallithea.model.meta import Base, Session + +from kallithea import DB_PREFIX URL_SEP = '/' log = logging.getLogger(__name__) @@ -144,8 +149,8 @@ class BaseModel(object): return '' % (self.__class__.__name__) -class RhodeCodeSetting(Base, BaseModel): - __tablename__ = 'rhodecode_settings' +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' __table_args__ = ( UniqueConstraint('app_settings_name'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -210,7 +215,7 @@ class RhodeCodeSetting(Base, BaseModel): raise Exception('Could not get application settings !') settings = {} for each in ret: - settings['rhodecode_' + each.app_settings_name] = \ + settings[each.app_settings_name] = \ each.app_settings_value return settings @@ -226,8 +231,8 @@ class RhodeCodeSetting(Base, BaseModel): return fd -class RhodeCodeUi(Base, BaseModel): - __tablename__ = 'rhodecode_ui' +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' __table_args__ = ( UniqueConstraint('ui_key'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -690,8 +695,8 @@ class Repository(Base, BaseModel): :param cls: """ - q = Session().query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == cls.url_sep()) + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -740,7 +745,7 @@ class Repository(Base, BaseModel): Returns base full path for that repository means where it actually exists on a filesystem """ - q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == + q = Session().query(Ui).filter(Ui.ui_key == Repository.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -778,20 +783,20 @@ class Repository(Base, BaseModel): """ Creates an db based ui object for this repository """ - from rhodecode.lib.utils import make_ui + from kallithea.lib.utils import make_ui return make_ui('db', clear_session=False) @classmethod def inject_ui(cls, repo, extras={}): - from rhodecode.lib.vcs.backends.hg import MercurialRepository - from rhodecode.lib.vcs.backends.git import GitRepository + from kallithea.lib.vcs.backends.hg import MercurialRepository + from kallithea.lib.vcs.backends.git import GitRepository required = (MercurialRepository, GitRepository) if not isinstance(repo, required): raise Exception('repo must be instance of %s' % (','.join(required))) # inject ui extra param to log this action via push logger for k, v in extras.items(): - repo._repo.ui.setconfig('rhodecode_extras', k, v) + repo._repo.ui.setconfig('extras', k, v) @classmethod def is_valid(cls, repo_name): @@ -801,7 +806,7 @@ class Repository(Base, BaseModel): :param cls: :param repo_name: """ - from rhodecode.lib.utils import is_valid_repo + from kallithea.lib.utils import is_valid_repo return is_valid_repo(repo_name, cls.base_path()) @@ -941,8 +946,8 @@ class Repository(Base, BaseModel): @LazyProperty def scm_instance(self): - import rhodecode - full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache')) + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) if full_cache: return self.scm_instance_cached() return self.__get_instance() @@ -1028,7 +1033,7 @@ class RepoGroup(Base, BaseModel): @classmethod def groups_choices(cls, check_perms=False): from webhelpers.html import literal as _literal - from rhodecode.model.scm import ScmModel + from kallithea.model.scm import ScmModel groups = cls.query().all() if check_perms: #filter group user have access to, it's done @@ -1170,16 +1175,16 @@ class Permission(Base, BaseModel): ('group.write', _('Repositories Group write access')), ('group.admin', _('Repositories Group admin access')), - ('hg.admin', _('RhodeCode Administrator')), + ('hg.admin', _('Kallithea Administrator')), ('hg.create.none', _('Repository creation disabled')), ('hg.create.repository', _('Repository creation enabled')), ('hg.fork.none', _('Repository forking disabled')), ('hg.fork.repository', _('Repository forking enabled')), ('hg.register.none', _('Register disabled')), - ('hg.register.manual_activate', _('Register new user with RhodeCode ' + ('hg.register.manual_activate', _('Register new user with Kallithea ' 'with manual activation')), - ('hg.register.auto_activate', _('Register new user with RhodeCode ' + ('hg.register.auto_activate', _('Register new user with Kallithea ' 'with auto activation')), ] @@ -1439,10 +1444,10 @@ class CacheInvalidation(Base, BaseModel) :param key: """ - import rhodecode + import kallithea prefix = '' org_key = key - iid = rhodecode.CONFIG.get('instance_id') + iid = kallithea.CONFIG.get('instance_id') if iid: prefix = iid @@ -1778,7 +1783,7 @@ class Notification(Base, BaseModel): @property def description(self): - from rhodecode.model.notification import NotificationModel + from kallithea.model.notification import NotificationModel return NotificationModel().make_description(self) diff --git a/rhodecode/lib/dbmigrate/schema/db_1_5_0.py b/kallithea/lib/dbmigrate/schema/db_1_5_0.py rename from rhodecode/lib/dbmigrate/schema/db_1_5_0.py rename to kallithea/lib/dbmigrate/schema/db_1_5_0.py --- a/rhodecode/lib/dbmigrate/schema/db_1_5_0.py +++ b/kallithea/lib/dbmigrate/schema/db_1_5_0.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.db_1_5_0 - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Database Models for RhodeCode <=1.5.2 - - :created_on: Apr 08, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.db_1_5_0 +~~~~~~~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea <=1.5.2 + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import os import logging @@ -40,17 +42,19 @@ from webob.exc import HTTPNotFound from pylons.i18n.translation import lazy_ugettext as _ -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ safe_unicode, remove_suffix, remove_prefix -from rhodecode.lib.compat import json -from rhodecode.lib.caching_query import FromCache +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache -from rhodecode.model.meta import Base, Session +from kallithea.model.meta import Base, Session + +from kallithea import DB_PREFIX URL_SEP = '/' log = logging.getLogger(__name__) @@ -144,8 +148,8 @@ class BaseModel(object): return '' % (self.__class__.__name__) -class RhodeCodeSetting(Base, BaseModel): - __tablename__ = 'rhodecode_settings' +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' __table_args__ = ( UniqueConstraint('app_settings_name'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -214,7 +218,7 @@ class RhodeCodeSetting(Base, BaseModel): raise Exception('Could not get application settings !') settings = {} for each in ret: - settings['rhodecode_' + each.app_settings_name] = \ + settings[each.app_settings_name] = \ each.app_settings_value return settings @@ -243,8 +247,8 @@ class RhodeCodeSetting(Base, BaseModel): return fd -class RhodeCodeUi(Base, BaseModel): - __tablename__ = 'rhodecode_ui' +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' __table_args__ = ( UniqueConstraint('ui_key'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -710,8 +714,8 @@ class Repository(Base, BaseModel): :param cls: """ - q = Session().query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == cls.url_sep()) + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -760,7 +764,7 @@ class Repository(Base, BaseModel): Returns base full path for that repository means where it actually exists on a filesystem """ - q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == + q = Session().query(Ui).filter(Ui.ui_key == Repository.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -798,20 +802,20 @@ class Repository(Base, BaseModel): """ Creates an db based ui object for this repository """ - from rhodecode.lib.utils import make_ui + from kallithea.lib.utils import make_ui return make_ui('db', clear_session=False) @classmethod def inject_ui(cls, repo, extras={}): - from rhodecode.lib.vcs.backends.hg import MercurialRepository - from rhodecode.lib.vcs.backends.git import GitRepository + from kallithea.lib.vcs.backends.hg import MercurialRepository + from kallithea.lib.vcs.backends.git import GitRepository required = (MercurialRepository, GitRepository) if not isinstance(repo, required): raise Exception('repo must be instance of %s' % (','.join(required))) # inject ui extra param to log this action via push logger for k, v in extras.items(): - repo._repo.ui.setconfig('rhodecode_extras', k, v) + repo._repo.ui.setconfig('extras', k, v) @classmethod def is_valid(cls, repo_name): @@ -821,7 +825,7 @@ class Repository(Base, BaseModel): :param cls: :param repo_name: """ - from rhodecode.lib.utils import is_valid_repo + from kallithea.lib.utils import is_valid_repo return is_valid_repo(repo_name, cls.base_path()) @@ -961,8 +965,8 @@ class Repository(Base, BaseModel): @LazyProperty def scm_instance(self): - import rhodecode - full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache')) + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) if full_cache: return self.scm_instance_cached() return self.__get_instance() @@ -1048,7 +1052,7 @@ class RepoGroup(Base, BaseModel): @classmethod def groups_choices(cls, check_perms=False): from webhelpers.html import literal as _literal - from rhodecode.model.scm import ScmModel + from kallithea.model.scm import ScmModel groups = cls.query().all() if check_perms: #filter group user have access to, it's done @@ -1190,16 +1194,16 @@ class Permission(Base, BaseModel): ('group.write', _('Repositories Group write access')), ('group.admin', _('Repositories Group admin access')), - ('hg.admin', _('RhodeCode Administrator')), + ('hg.admin', _('Kallithea Administrator')), ('hg.create.none', _('Repository creation disabled')), ('hg.create.repository', _('Repository creation enabled')), ('hg.fork.none', _('Repository forking disabled')), ('hg.fork.repository', _('Repository forking enabled')), ('hg.register.none', _('Register disabled')), - ('hg.register.manual_activate', _('Register new user with RhodeCode ' + ('hg.register.manual_activate', _('Register new user with Kallithea ' 'with manual activation')), - ('hg.register.auto_activate', _('Register new user with RhodeCode ' + ('hg.register.auto_activate', _('Register new user with Kallithea ' 'with auto activation')), ] @@ -1221,6 +1225,14 @@ class Permission(Base, BaseModel): 'hg.create.repository':1 } + DEFAULT_USER_PERMISSIONS = [ + 'repository.read', + 'group.read', + 'hg.create.repository', + 'hg.fork.repository', + 'hg.register.manual_activate', + ] + permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) @@ -1459,10 +1471,10 @@ class CacheInvalidation(Base, BaseModel) :param key: """ - import rhodecode + import kallithea prefix = '' org_key = key - iid = rhodecode.CONFIG.get('instance_id') + iid = kallithea.CONFIG.get('instance_id') if iid: prefix = iid @@ -1798,7 +1810,7 @@ class Notification(Base, BaseModel): @property def description(self): - from rhodecode.model.notification import NotificationModel + from kallithea.model.notification import NotificationModel return NotificationModel().make_description(self) diff --git a/rhodecode/lib/dbmigrate/schema/db_1_5_2.py b/kallithea/lib/dbmigrate/schema/db_1_5_2.py rename from rhodecode/lib/dbmigrate/schema/db_1_5_2.py rename to kallithea/lib/dbmigrate/schema/db_1_5_2.py --- a/rhodecode/lib/dbmigrate/schema/db_1_5_2.py +++ b/kallithea/lib/dbmigrate/schema/db_1_5_2.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.db_1_5_2 - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Database Models for RhodeCode <=1.5.X - - :created_on: Apr 08, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.db_1_5_2 +~~~~~~~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea <=1.5.X + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import os import logging @@ -40,22 +42,24 @@ from webob.exc import HTTPNotFound from pylons.i18n.translation import lazy_ugettext as _ -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.backends.base import EmptyChangeset +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ safe_unicode, remove_suffix, remove_prefix -from rhodecode.lib.compat import json -from rhodecode.lib.caching_query import FromCache +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache -from rhodecode.model.meta import Base, Session +from kallithea.model.meta import Base, Session URL_SEP = '/' log = logging.getLogger(__name__) +from kallithea import DB_PREFIX + #============================================================================== # BASE CLASSES #============================================================================== @@ -145,8 +149,8 @@ class BaseModel(object): return '' % (self.__class__.__name__) -class RhodeCodeSetting(Base, BaseModel): - __tablename__ = 'rhodecode_settings' +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' __table_args__ = ( UniqueConstraint('app_settings_name'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -215,7 +219,7 @@ class RhodeCodeSetting(Base, BaseModel): raise Exception('Could not get application settings !') settings = {} for each in ret: - settings['rhodecode_' + each.app_settings_name] = \ + settings[each.app_settings_name] = \ each.app_settings_value return settings @@ -244,8 +248,8 @@ class RhodeCodeSetting(Base, BaseModel): return fd -class RhodeCodeUi(Base, BaseModel): - __tablename__ = 'rhodecode_ui' +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' __table_args__ = ( UniqueConstraint('ui_key'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -542,7 +546,7 @@ class UserIpMap(Base, BaseModel): @classmethod def _get_ip_range(cls, ip_addr): - from rhodecode.lib import ipaddr + from kallithea.lib import ipaddr net = ipaddr.IPv4Network(ip_addr) return [str(net.network), str(net.broadcast)] @@ -701,7 +705,7 @@ class Repository(Base, BaseModel): def __unicode__(self): return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, - self.repo_name) + safe_unicode(self.repo_name)) @hybrid_property def locked(self): @@ -720,7 +724,7 @@ class Repository(Base, BaseModel): @hybrid_property def changeset_cache(self): - from rhodecode.lib.vcs.backends.base import EmptyChangeset + from kallithea.lib.vcs.backends.base import EmptyChangeset dummy = EmptyChangeset().__json__() if not self._changeset_cache: return dummy @@ -776,8 +780,8 @@ class Repository(Base, BaseModel): :param cls: """ - q = Session().query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == cls.url_sep()) + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -826,7 +830,7 @@ class Repository(Base, BaseModel): Returns base full path for that repository means where it actually exists on a filesystem """ - q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == + q = Session().query(Ui).filter(Ui.ui_key == Repository.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -864,20 +868,20 @@ class Repository(Base, BaseModel): """ Creates an db based ui object for this repository """ - from rhodecode.lib.utils import make_ui + from kallithea.lib.utils import make_ui return make_ui('db', clear_session=False) @classmethod def inject_ui(cls, repo, extras={}): - from rhodecode.lib.vcs.backends.hg import MercurialRepository - from rhodecode.lib.vcs.backends.git import GitRepository + from kallithea.lib.vcs.backends.hg import MercurialRepository + from kallithea.lib.vcs.backends.git import GitRepository required = (MercurialRepository, GitRepository) if not isinstance(repo, required): raise Exception('repo must be instance of %s' % (','.join(required))) # inject ui extra param to log this action via push logger for k, v in extras.items(): - repo._repo.ui.setconfig('rhodecode_extras', k, v) + repo._repo.ui.setconfig('extras', k, v) @classmethod def is_valid(cls, repo_name): @@ -887,7 +891,7 @@ class Repository(Base, BaseModel): :param cls: :param repo_name: """ - from rhodecode.lib.utils import is_valid_repo + from kallithea.lib.utils import is_valid_repo return is_valid_repo(repo_name, cls.base_path()) @@ -978,7 +982,7 @@ class Repository(Base, BaseModel): :param cs_cache: """ - from rhodecode.lib.vcs.backends.base import BaseChangeset + from kallithea.lib.vcs.backends.base import BaseChangeset if cs_cache is None: cs_cache = EmptyChangeset() # use no-cache version here @@ -1081,8 +1085,8 @@ class Repository(Base, BaseModel): @LazyProperty def scm_instance(self): - import rhodecode - full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache')) + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) if full_cache: return self.scm_instance_cached() return self.__get_instance() @@ -1168,7 +1172,7 @@ class RepoGroup(Base, BaseModel): @classmethod def groups_choices(cls, check_perms=False): from webhelpers.html import literal as _literal - from rhodecode.model.scm import ScmModel + from kallithea.model.scm import ScmModel groups = cls.query().all() if check_perms: #filter group user have access to, it's done @@ -1310,16 +1314,16 @@ class Permission(Base, BaseModel): ('group.write', _('Repositories Group write access')), ('group.admin', _('Repositories Group admin access')), - ('hg.admin', _('RhodeCode Administrator')), + ('hg.admin', _('Kallithea Administrator')), ('hg.create.none', _('Repository creation disabled')), ('hg.create.repository', _('Repository creation enabled')), ('hg.fork.none', _('Repository forking disabled')), ('hg.fork.repository', _('Repository forking enabled')), ('hg.register.none', _('Register disabled')), - ('hg.register.manual_activate', _('Register new user with RhodeCode ' + ('hg.register.manual_activate', _('Register new user with Kallithea ' 'with manual activation')), - ('hg.register.auto_activate', _('Register new user with RhodeCode ' + ('hg.register.auto_activate', _('Register new user with Kallithea ' 'with auto activation')), ] @@ -1579,10 +1583,10 @@ class CacheInvalidation(Base, BaseModel) :param key: """ - import rhodecode + import kallithea prefix = '' org_key = key - iid = rhodecode.CONFIG.get('instance_id') + iid = kallithea.CONFIG.get('instance_id') if iid: prefix = iid @@ -1926,7 +1930,7 @@ class Notification(Base, BaseModel): @property def description(self): - from rhodecode.model.notification import NotificationModel + from kallithea.model.notification import NotificationModel return NotificationModel().make_description(self) diff --git a/rhodecode/lib/dbmigrate/schema/db_1_6_0.py b/kallithea/lib/dbmigrate/schema/db_1_6_0.py rename from rhodecode/lib/dbmigrate/schema/db_1_6_0.py rename to kallithea/lib/dbmigrate/schema/db_1_6_0.py --- a/rhodecode/lib/dbmigrate/schema/db_1_6_0.py +++ b/kallithea/lib/dbmigrate/schema/db_1_6_0.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.db_1_6_0 - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Database Models for RhodeCode <=1.5.X - - :created_on: Apr 08, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.db_1_6_0 +~~~~~~~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea <=1.5.X + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import os import logging @@ -40,22 +42,24 @@ from webob.exc import HTTPNotFound from pylons.i18n.translation import lazy_ugettext as _ -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.backends.base import EmptyChangeset +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ safe_unicode, remove_suffix, remove_prefix, time_to_datetime, _set_extras -from rhodecode.lib.compat import json -from rhodecode.lib.caching_query import FromCache +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache -from rhodecode.model.meta import Base, Session +from kallithea.model.meta import Base, Session URL_SEP = '/' log = logging.getLogger(__name__) +from kallithea import DB_PREFIX + #============================================================================== # BASE CLASSES #============================================================================== @@ -145,8 +149,8 @@ class BaseModel(object): return '' % (self.__class__.__name__) -class RhodeCodeSetting(Base, BaseModel): - __tablename__ = 'rhodecode_settings' +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' __table_args__ = ( UniqueConstraint('app_settings_name'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -215,7 +219,7 @@ class RhodeCodeSetting(Base, BaseModel): raise Exception('Could not get application settings !') settings = {} for each in ret: - settings['rhodecode_' + each.app_settings_name] = \ + settings[each.app_settings_name] = \ each.app_settings_value return settings @@ -244,8 +248,8 @@ class RhodeCodeSetting(Base, BaseModel): return fd -class RhodeCodeUi(Base, BaseModel): - __tablename__ = 'rhodecode_ui' +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' __table_args__ = ( UniqueConstraint('ui_key'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -405,7 +409,7 @@ class User(Base, BaseModel): """ Returns instance of AuthUser for this user """ - from rhodecode.lib.auth import AuthUser + from kallithea.lib.auth import AuthUser return AuthUser(user_id=self.user_id, api_key=self.api_key, username=self.username) @@ -471,7 +475,7 @@ class User(Base, BaseModel): :param author: """ - from rhodecode.lib.helpers import email, author_name + from kallithea.lib.helpers import email, author_name # Valid email in the attribute passed, see if they're in the system _email = email(author) if _email: @@ -571,7 +575,7 @@ class UserIpMap(Base, BaseModel): @classmethod def _get_ip_range(cls, ip_addr): - from rhodecode.lib import ipaddr + from kallithea.lib import ipaddr net = ipaddr.IPNetwork(address=ip_addr) return [str(net.network), str(net.broadcast)] @@ -770,7 +774,7 @@ class Repository(Base, BaseModel): def __unicode__(self): return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, - self.repo_name) + safe_unicode(self.repo_name)) @hybrid_property def locked(self): @@ -789,7 +793,7 @@ class Repository(Base, BaseModel): @hybrid_property def changeset_cache(self): - from rhodecode.lib.vcs.backends.base import EmptyChangeset + from kallithea.lib.vcs.backends.base import EmptyChangeset dummy = EmptyChangeset().__json__() if not self._changeset_cache: return dummy @@ -845,8 +849,8 @@ class Repository(Base, BaseModel): :param cls: """ - q = Session().query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == cls.url_sep()) + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -895,7 +899,7 @@ class Repository(Base, BaseModel): Returns base full path for that repository means where it actually exists on a filesystem """ - q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == + q = Session().query(Ui).filter(Ui.ui_key == Repository.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -933,7 +937,7 @@ class Repository(Base, BaseModel): """ Creates an db based ui object for this repository """ - from rhodecode.lib.utils import make_ui + from kallithea.lib.utils import make_ui return make_ui('db', clear_session=False) @classmethod @@ -944,7 +948,7 @@ class Repository(Base, BaseModel): :param cls: :param repo_name: """ - from rhodecode.lib.utils import is_valid_repo + from kallithea.lib.utils import is_valid_repo return is_valid_repo(repo_name, cls.base_path()) @@ -974,8 +978,8 @@ class Repository(Base, BaseModel): locked_date=time_to_datetime(self.locked[1]) \ if self.locked[1] else None ) - rc_config = RhodeCodeSetting.get_app_settings() - repository_fields = str2bool(rc_config.get('rhodecode_repository_fields')) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) if repository_fields: for f in self.extra_fields: data[f.field_key_prefixed] = f.field_value @@ -1048,7 +1052,7 @@ class Repository(Base, BaseModel): :param cs_cache: """ - from rhodecode.lib.vcs.backends.base import BaseChangeset + from kallithea.lib.vcs.backends.base import BaseChangeset if cs_cache is None: cs_cache = EmptyChangeset() # use no-cache version here @@ -1133,7 +1137,7 @@ class Repository(Base, BaseModel): return grouped def _repo_size(self): - from rhodecode.lib import helpers as h + from kallithea.lib import helpers as h log.debug('calculating repository size...') return h.format_byte_size(self.scm_instance.size) @@ -1156,8 +1160,8 @@ class Repository(Base, BaseModel): @LazyProperty def scm_instance(self): - import rhodecode - full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache')) + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) if full_cache: return self.scm_instance_cached() return self.__get_instance() @@ -1395,16 +1399,16 @@ class Permission(Base, BaseModel): ('group.write', _('Repository group write access')), ('group.admin', _('Repository group admin access')), - ('hg.admin', _('RhodeCode Administrator')), + ('hg.admin', _('Kallithea Administrator')), ('hg.create.none', _('Repository creation disabled')), ('hg.create.repository', _('Repository creation enabled')), ('hg.fork.none', _('Repository forking disabled')), ('hg.fork.repository', _('Repository forking enabled')), ('hg.register.none', _('Register disabled')), - ('hg.register.manual_activate', _('Register new user with RhodeCode ' + ('hg.register.manual_activate', _('Register new user with Kallithea ' 'with manual activation')), - ('hg.register.auto_activate', _('Register new user with RhodeCode ' + ('hg.register.auto_activate', _('Register new user with Kallithea ' 'with auto activation')), ] @@ -1665,8 +1669,8 @@ class CacheInvalidation(Base, BaseModel) """ Wrapper for generating a unique cache key for this instance and "key". """ - import rhodecode - prefix = rhodecode.CONFIG.get('instance_id', '') + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') return "%s%s" % (prefix, key) @classmethod @@ -2005,7 +2009,7 @@ class Notification(Base, BaseModel): @property def description(self): - from rhodecode.model.notification import NotificationModel + from kallithea.model.notification import NotificationModel return NotificationModel().make_description(self) diff --git a/rhodecode/lib/dbmigrate/schema/db_1_7_0.py b/kallithea/lib/dbmigrate/schema/db_1_7_0.py rename from rhodecode/lib/dbmigrate/schema/db_1_7_0.py rename to kallithea/lib/dbmigrate/schema/db_1_7_0.py --- a/rhodecode/lib/dbmigrate/schema/db_1_7_0.py +++ b/kallithea/lib/dbmigrate/schema/db_1_7_0.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.db - ~~~~~~~~~~~~~~~~~~ - - Database Models for RhodeCode - - :created_on: Apr 08, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.db +~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import os import time @@ -40,22 +42,24 @@ from webob.exc import HTTPNotFound from pylons.i18n.translation import lazy_ugettext as _ -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.backends.base import EmptyChangeset +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ safe_unicode, remove_suffix, remove_prefix, time_to_datetime, _set_extras -from rhodecode.lib.compat import json -from rhodecode.lib.caching_query import FromCache +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache -from rhodecode.model.meta import Base, Session +from kallithea.model.meta import Base, Session URL_SEP = '/' log = logging.getLogger(__name__) +from kallithea import DB_PREFIX + #============================================================================== # BASE CLASSES #============================================================================== @@ -150,8 +154,8 @@ class BaseModel(object): return '' % (self.__class__.__name__) -class RhodeCodeSetting(Base, BaseModel): - __tablename__ = 'rhodecode_settings' +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' __table_args__ = ( UniqueConstraint('app_settings_name'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -220,7 +224,7 @@ class RhodeCodeSetting(Base, BaseModel): raise Exception('Could not get application settings !') settings = {} for each in ret: - settings['rhodecode_' + each.app_settings_name] = \ + settings[each.app_settings_name] = \ each.app_settings_value return settings @@ -249,8 +253,8 @@ class RhodeCodeSetting(Base, BaseModel): return fd -class RhodeCodeUi(Base, BaseModel): - __tablename__ = 'rhodecode_ui' +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' __table_args__ = ( UniqueConstraint('ui_key'), {'extend_existing': True, 'mysql_engine': 'InnoDB', @@ -407,7 +411,7 @@ class User(Base, BaseModel): """ Returns instance of AuthUser for this user """ - from rhodecode.lib.auth import AuthUser + from kallithea.lib.auth import AuthUser return AuthUser(user_id=self.user_id, api_key=self.api_key, username=self.username) @@ -473,7 +477,7 @@ class User(Base, BaseModel): :param author: """ - from rhodecode.lib.helpers import email, author_name + from kallithea.lib.helpers import email, author_name # Valid email in the attribute passed, see if they're in the system _email = email(author) if _email: @@ -587,7 +591,7 @@ class UserIpMap(Base, BaseModel): @classmethod def _get_ip_range(cls, ip_addr): - from rhodecode.lib import ipaddr + from kallithea.lib import ipaddr net = ipaddr.IPNetwork(address=ip_addr) return [str(net.network), str(net.broadcast)] @@ -799,7 +803,7 @@ class Repository(Base, BaseModel): def __unicode__(self): return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, - self.repo_name) + safe_unicode(self.repo_name)) @hybrid_property def locked(self): @@ -818,7 +822,7 @@ class Repository(Base, BaseModel): @hybrid_property def changeset_cache(self): - from rhodecode.lib.vcs.backends.base import EmptyChangeset + from kallithea.lib.vcs.backends.base import EmptyChangeset dummy = EmptyChangeset().__json__() if not self._changeset_cache: return dummy @@ -874,8 +878,8 @@ class Repository(Base, BaseModel): :param cls: """ - q = Session().query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == cls.url_sep()) + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -924,7 +928,7 @@ class Repository(Base, BaseModel): Returns base full path for that repository means where it actually exists on a filesystem """ - q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == + q = Session().query(Ui).filter(Ui.ui_key == Repository.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -962,7 +966,7 @@ class Repository(Base, BaseModel): """ Creates an db based ui object for this repository """ - from rhodecode.lib.utils import make_ui + from kallithea.lib.utils import make_ui return make_ui('db', clear_session=False) @classmethod @@ -973,7 +977,7 @@ class Repository(Base, BaseModel): :param cls: :param repo_name: """ - from rhodecode.lib.utils import is_valid_repo + from kallithea.lib.utils import is_valid_repo return is_valid_repo(repo_name, cls.base_path()) @@ -1003,8 +1007,8 @@ class Repository(Base, BaseModel): locked_date=time_to_datetime(self.locked[1]) \ if self.locked[1] else None ) - rc_config = RhodeCodeSetting.get_app_settings() - repository_fields = str2bool(rc_config.get('rhodecode_repository_fields')) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) if repository_fields: for f in self.extra_fields: data[f.field_key_prefixed] = f.field_value @@ -1079,7 +1083,7 @@ class Repository(Base, BaseModel): :param cs_cache: """ - from rhodecode.lib.vcs.backends.base import BaseChangeset + from kallithea.lib.vcs.backends.base import BaseChangeset if cs_cache is None: cs_cache = EmptyChangeset() # use no-cache version here @@ -1163,7 +1167,7 @@ class Repository(Base, BaseModel): return grouped def _repo_size(self): - from rhodecode.lib import helpers as h + from kallithea.lib import helpers as h log.debug('calculating repository size...') return h.format_byte_size(self.scm_instance.size) @@ -1182,8 +1186,8 @@ class Repository(Base, BaseModel): @property def scm_instance(self): - import rhodecode - full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache')) + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) if full_cache: return self.scm_instance_cached() return self.__get_instance() @@ -1403,7 +1407,7 @@ class Permission(Base, BaseModel): 'mysql_charset': 'utf8'}, ) PERMS = [ - ('hg.admin', _('RhodeCode Administrator')), + ('hg.admin', _('Kallithea Administrator')), ('repository.none', _('Repository no access')), ('repository.read', _('Repository read access')), @@ -1815,8 +1819,8 @@ class CacheInvalidation(Base, BaseModel) Wrapper for generating a unique cache key for this instance and "key". key must / will start with a repo_name which will be stored in .cache_args . """ - import rhodecode - prefix = rhodecode.CONFIG.get('instance_id', '') + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') return "%s%s" % (prefix, key) @classmethod @@ -2101,7 +2105,7 @@ class Notification(Base, BaseModel): @property def description(self): - from rhodecode.model.notification import NotificationModel + from kallithea.model.notification import NotificationModel return NotificationModel().make_description(self) @@ -2160,8 +2164,8 @@ class Gist(Base, BaseModel): return cls.query().filter(cls.gist_access_id == gist_access_id).scalar() def gist_url(self): - import rhodecode - alias_url = rhodecode.CONFIG.get('gist_alias_url') + import kallithea + alias_url = kallithea.CONFIG.get('gist_alias_url') if alias_url: return alias_url.replace('{gistid}', self.gist_access_id) @@ -2175,9 +2179,9 @@ class Gist(Base, BaseModel): :param cls: """ - from rhodecode.model.gist import GIST_STORE_LOC - q = Session().query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == URL_SEP) + from kallithea.model.gist import GIST_STORE_LOC + q = Session().query(Ui)\ + .filter(Ui.ui_key == URL_SEP) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return os.path.join(q.one().ui_value, GIST_STORE_LOC) @@ -2206,7 +2210,7 @@ class Gist(Base, BaseModel): @property def scm_instance(self): - from rhodecode.lib.vcs import get_repo + from kallithea.lib.vcs import get_repo base_path = self.base_path() return get_repo(os.path.join(*map(safe_str, [base_path, self.gist_access_id]))) diff --git a/kallithea/lib/dbmigrate/schema/db_1_8_0.py b/kallithea/lib/dbmigrate/schema/db_1_8_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/schema/db_1_8_0.py @@ -0,0 +1,2274 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.db +~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import os +import time +import logging +import datetime +import traceback +import hashlib +import collections + +from sqlalchemy import * +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import relationship, joinedload, class_mapper, validates +from sqlalchemy.exc import DatabaseError +from beaker.cache import cache_region, region_invalidate +from webob.exc import HTTPNotFound + +from pylons.i18n.translation import lazy_ugettext as _ + +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset + +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ + safe_unicode, remove_suffix, remove_prefix, time_to_datetime, _set_extras +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache + +from kallithea.model.meta import Base, Session + +URL_SEP = '/' +log = logging.getLogger(__name__) + +from kallithea import DB_PREFIX + +#============================================================================== +# BASE CLASSES +#============================================================================== + +_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest() + + +class BaseModel(object): + """ + Base Model for all classess + """ + + @classmethod + def _get_keys(cls): + """return column names for this model """ + return class_mapper(cls).c.keys() + + def get_dict(self): + """ + return dict with keys and values corresponding + to this model data """ + + d = {} + for k in self._get_keys(): + d[k] = getattr(self, k) + + # also use __json__() if present to get additional fields + _json_attr = getattr(self, '__json__', None) + if _json_attr: + # update with attributes from __json__ + if callable(_json_attr): + _json_attr = _json_attr() + for k, val in _json_attr.iteritems(): + d[k] = val + return d + + def get_appstruct(self): + """return list with keys and values tupples corresponding + to this model data """ + + l = [] + for k in self._get_keys(): + l.append((k, getattr(self, k),)) + return l + + def populate_obj(self, populate_dict): + """populate model with data from given populate_dict""" + + for k in self._get_keys(): + if k in populate_dict: + setattr(self, k, populate_dict[k]) + + @classmethod + def query(cls): + return Session().query(cls) + + @classmethod + def get(cls, id_): + if id_: + return cls.query().get(id_) + + @classmethod + def get_or_404(cls, id_): + try: + id_ = int(id_) + except (TypeError, ValueError): + raise HTTPNotFound + + res = cls.query().get(id_) + if not res: + raise HTTPNotFound + return res + + @classmethod + def getAll(cls): + # deprecated and left for backward compatibility + return cls.get_all() + + @classmethod + def get_all(cls): + return cls.query().all() + + @classmethod + def delete(cls, id_): + obj = cls.query().get(id_) + Session().delete(obj) + + def __repr__(self): + if hasattr(self, '__unicode__'): + # python repr needs to return str + return safe_str(self.__unicode__()) + return '' % (self.__class__.__name__) + + +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' + __table_args__ = ( + UniqueConstraint('app_settings_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + app_settings_name = Column("app_settings_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_value = Column("app_settings_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_type = Column("app_settings_type", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __init__(self, key='', val='', type='unicode'): + self.app_settings_name = key + self.app_settings_value = val + self.app_settings_type = type + + @validates('_app_settings_value') + def validate_settings_value(self, key, val): + assert type(val) == unicode + return val + + @hybrid_property + def app_settings_value(self): + v = self._app_settings_value + if self.app_settings_name in ["ldap_active", + "default_repo_enable_statistics", + "default_repo_enable_locking", + "default_repo_private", + "default_repo_enable_downloads"]: + v = str2bool(v) + return v + + @app_settings_value.setter + def app_settings_value(self, val): + """ + Setter that will always make sure we use unicode in app_settings_value + + :param val: + """ + self._app_settings_value = safe_unicode(val) + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, + self.app_settings_name, self.app_settings_value + ) + + @classmethod + def get_by_name(cls, key): + return cls.query()\ + .filter(cls.app_settings_name == key).scalar() + + @classmethod + def get_by_name_or_create(cls, key): + res = cls.get_by_name(key) + if not res: + res = cls(key) + return res + + @classmethod + def get_app_settings(cls, cache=False): + + ret = cls.query() + + if cache: + ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) + + if not ret: + raise Exception('Could not get application settings !') + settings = {} + for each in ret: + settings[each.app_settings_name] = \ + each.app_settings_value + + return settings + + @classmethod + def get_ldap_settings(cls, cache=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('ldap_')).all() + fd = {} + for row in ret: + fd.update({row.app_settings_name: row.app_settings_value}) + + return fd + + @classmethod + def get_default_repo_settings(cls, cache=False, strip_prefix=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('default_')).all() + fd = {} + for row in ret: + key = row.app_settings_name + if strip_prefix: + key = remove_prefix(key, prefix='default_') + fd.update({key: row.app_settings_value}) + + return fd + + @classmethod + def get_server_info(cls): + import pkg_resources + import platform + import kallithea + from kallithea.lib.utils import check_git_version + mods = [(p.project_name, p.version) for p in pkg_resources.working_set] + mods += [('git', str(check_git_version()))] + info = { + 'modules': sorted(mods, key=lambda k: k[0].lower()), + 'py_version': platform.python_version(), + 'platform': platform.platform(), + 'kallithea_version': kallithea.__version__ + } + return info + + +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' + __table_args__ = ( + UniqueConstraint('ui_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + HOOK_UPDATE = 'changegroup.update' + HOOK_REPO_SIZE = 'changegroup.repo_size' + HOOK_PUSH = 'changegroup.push_logger' + HOOK_PRE_PUSH = 'prechangegroup.pre_push' + HOOK_PULL = 'outgoing.pull_logger' + HOOK_PRE_PULL = 'preoutgoing.pre_pull' + + ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) + + # def __init__(self, section='', key='', value=''): + # self.ui_section = section + # self.ui_key = key + # self.ui_value = value + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.ui_key == key).scalar() + + @classmethod + def get_builtin_hooks(cls): + q = cls.query() + q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + return q.all() + + @classmethod + def get_custom_hooks(cls): + q = cls.query() + q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + q = q.filter(cls.ui_section == 'hooks') + return q.all() + + @classmethod + def get_repos_location(cls): + return cls.get_by_key('/').ui_value + + @classmethod + def create_or_update_hook(cls, key, val): + new_ui = cls.get_by_key(key) or cls() + new_ui.ui_section = 'hooks' + new_ui.ui_active = True + new_ui.ui_key = key + new_ui.ui_value = val + + Session().add(new_ui) + + def __repr__(self): + return '' % (self.__class__.__name__, self.ui_key, + self.ui_value) + + +class User(Base, BaseModel): + __tablename__ = 'users' + __table_args__ = ( + UniqueConstraint('username'), UniqueConstraint('email'), + Index('u_username_idx', 'username'), + Index('u_email_idx', 'email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + DEFAULT_USER = 'default' + + user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + admin = Column("admin", Boolean(), nullable=True, unique=None, default=False) + name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) + ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + + user_log = relationship('UserLog') + user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') + + repositories = relationship('Repository') + user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all') + followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all') + + repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all') + repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all') + + group_member = relationship('UserGroupMember', cascade='all') + + notifications = relationship('UserNotification', cascade='all') + # notifications assigned to this user + user_created_notifications = relationship('Notification', cascade='all') + # comments created by this user + user_comments = relationship('ChangesetComment', cascade='all') + #extra emails for this user + user_emails = relationship('UserEmailMap', cascade='all') + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + @property + def firstname(self): + # alias for future + return self.name + + @property + def emails(self): + other = UserEmailMap.query().filter(UserEmailMap.user==self).all() + return [self.email] + [x.email for x in other] + + @property + def ip_addresses(self): + ret = UserIpMap.query().filter(UserIpMap.user == self).all() + return [x.ip_addr for x in ret] + + @property + def username_and_name(self): + return '%s (%s %s)' % (self.username, self.firstname, self.lastname) + + @property + def full_name(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def full_name_or_username(self): + return ('%s %s' % (self.firstname, self.lastname) + if (self.firstname and self.lastname) else self.username) + + @property + def full_contact(self): + return '%s %s <%s>' % (self.firstname, self.lastname, self.email) + + @property + def short_contact(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def is_admin(self): + return self.admin + + @property + def AuthUser(self): + """ + Returns instance of AuthUser for this user + """ + from kallithea.lib.auth import AuthUser + return AuthUser(user_id=self.user_id, api_key=self.api_key, + username=self.username) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.user_id, self.username) + + @classmethod + def get_by_username(cls, username, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.username.ilike(username)) + else: + q = cls.query().filter(cls.username == username) + + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(username) + ) + ) + return q.scalar() + + @classmethod + def get_by_api_key(cls, api_key, cache=False): + q = cls.query().filter(cls.api_key == api_key) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_api_key_%s" % api_key)) + return q.scalar() + + @classmethod + def get_by_email(cls, email, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.email.ilike(email)) + else: + q = cls.query().filter(cls.email == email) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_key_%s" % email)) + + ret = q.scalar() + if ret is None: + q = UserEmailMap.query() + # try fetching in alternate email map + if case_insensitive: + q = q.filter(UserEmailMap.email.ilike(email)) + else: + q = q.filter(UserEmailMap.email == email) + q = q.options(joinedload(UserEmailMap.user)) + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_map_key_%s" % email)) + ret = getattr(q.scalar(), 'user', None) + + return ret + + @classmethod + def get_from_cs_author(cls, author): + """ + Tries to get User objects out of commit author string + + :param author: + """ + from kallithea.lib.helpers import email, author_name + # Valid email in the attribute passed, see if they're in the system + _email = email(author) + if _email: + user = cls.get_by_email(_email, case_insensitive=True) + if user: + return user + # Maybe we can match by username? + _author = author_name(author) + user = cls.get_by_username(_author, case_insensitive=True) + if user: + return user + + def update_lastlogin(self): + """Update user lastlogin""" + self.last_login = datetime.datetime.now() + Session().add(self) + log.debug('updated user %s lastlogin' % self.username) + + @classmethod + def get_first_admin(cls): + user = User.query().filter(User.admin == True).first() + if user is None: + raise Exception('Missing administrative account!') + return user + + @classmethod + def get_default_user(cls, cache=False): + user = User.get_by_username(User.DEFAULT_USER, cache=cache) + if user is None: + raise Exception('Missing default account!') + return user + + def get_api_data(self): + """ + Common function for generating user related data for API + """ + user = self + data = dict( + user_id=user.user_id, + username=user.username, + firstname=user.name, + lastname=user.lastname, + email=user.email, + emails=user.emails, + api_key=user.api_key, + active=user.active, + admin=user.admin, + ldap_dn=user.ldap_dn, + last_login=user.last_login, + ip_addresses=user.ip_addresses + ) + return data + + def __json__(self): + data = dict( + full_name=self.full_name, + full_name_or_username=self.full_name_or_username, + short_contact=self.short_contact, + full_contact=self.full_contact + ) + data.update(self.get_api_data()) + return data + + +class UserEmailMap(Base, BaseModel): + __tablename__ = 'user_email_map' + __table_args__ = ( + Index('uem_email_idx', 'email'), + UniqueConstraint('email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + user = relationship('User', lazy='joined') + + @validates('_email') + def validate_email(self, key, email): + # check if this email is not main one + main_email = Session().query(User).filter(User.email == email).scalar() + if main_email is not None: + raise AttributeError('email %s is present is user table' % email) + return email + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + +class UserIpMap(Base, BaseModel): + __tablename__ = 'user_ip_map' + __table_args__ = ( + UniqueConstraint('user_id', 'ip_addr'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + user = relationship('User', lazy='joined') + + @classmethod + def _get_ip_range(cls, ip_addr): + from kallithea.lib import ipaddr + net = ipaddr.IPNetwork(address=ip_addr) + return [str(net.network), str(net.broadcast)] + + def __json__(self): + return dict( + ip_addr=self.ip_addr, + ip_range=self._get_ip_range(self.ip_addr) + ) + + +class UserLog(Base, BaseModel): + __tablename__ = 'user_logs' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True) + repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.repository_name, + self.action) + + @property + def action_as_day(self): + return datetime.date(*self.action_date.timetuple()[:3]) + + user = relationship('User') + repository = relationship('Repository', cascade='') + + +class UserGroup(Base, BaseModel): + __tablename__ = 'users_groups' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + + members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined") + users_group_to_perm = relationship('UserGroupToPerm', cascade='all') + users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all') + user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all') + + user = relationship('User') + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.users_group_id, + self.users_group_name) + + @classmethod + def get_by_group_name(cls, group_name, cache=False, + case_insensitive=False): + if case_insensitive: + q = cls.query().filter(cls.users_group_name.ilike(group_name)) + else: + q = cls.query().filter(cls.users_group_name == group_name) + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(group_name) + ) + ) + return q.scalar() + + @classmethod + def get(cls, user_group_id, cache=False): + user_group = cls.query() + if cache: + user_group = user_group.options(FromCache("sql_cache_short", + "get_users_group_%s" % user_group_id)) + return user_group.get(user_group_id) + + def get_api_data(self, with_members=True): + user_group = self + + data = dict( + users_group_id=user_group.users_group_id, + group_name=user_group.users_group_name, + active=user_group.users_group_active, + owner=user_group.user.username, + ) + if with_members: + members = [] + for user in user_group.members: + user = user.user + members.append(user.get_api_data()) + data['members'] = members + + return data + + +class UserGroupMember(Base, BaseModel): + __tablename__ = 'users_groups_members' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + + user = relationship('User', lazy='joined') + users_group = relationship('UserGroup') + + def __init__(self, gr_id='', u_id=''): + self.users_group_id = gr_id + self.user_id = u_id + + +class RepositoryField(Base, BaseModel): + __tablename__ = 'repositories_fields' + __table_args__ = ( + UniqueConstraint('repository_id', 'field_key'), # no-multi field + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields + + repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + field_key = Column("field_key", String(250, convert_unicode=False, assert_unicode=None)) + field_label = Column("field_label", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_value = Column("field_value", String(10000, convert_unicode=False, assert_unicode=None), nullable=False) + field_desc = Column("field_desc", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_type = Column("field_type", String(256), nullable=False, unique=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repository = relationship('Repository') + + @property + def field_key_prefixed(self): + return 'ex_%s' % self.field_key + + @classmethod + def un_prefix_key(cls, key): + if key.startswith(cls.PREFIX): + return key[len(cls.PREFIX):] + return key + + @classmethod + def get_by_key_name(cls, key, repo): + row = cls.query()\ + .filter(cls.repository == repo)\ + .filter(cls.field_key == key).scalar() + return row + + +class Repository(Base, BaseModel): + __tablename__ = 'repositories' + __table_args__ = ( + UniqueConstraint('repo_name'), + Index('r_repo_name_idx', 'repo_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + private = Column("private", Boolean(), nullable=True, unique=None, default=None) + enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True) + enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True) + description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data + + fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) + + user = relationship('User') + fork = relationship('Repository', remote_side=repo_id) + group = relationship('RepoGroup') + repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + stats = relationship('Statistics', cascade='all', uselist=False) + + followers = relationship('UserFollowing', + primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', + cascade='all') + extra_fields = relationship('RepositoryField', + cascade="all, delete, delete-orphan") + + logs = relationship('UserLog') + comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan") + + pull_requests_org = relationship('PullRequest', + primaryjoin='PullRequest.org_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + pull_requests_other = relationship('PullRequest', + primaryjoin='PullRequest.other_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, + safe_unicode(self.repo_name)) + + @hybrid_property + def locked(self): + # always should return [user_id, timelocked] + if self._locked: + _lock_info = self._locked.split(':') + return int(_lock_info[0]), _lock_info[1] + return [None, None] + + @locked.setter + def locked(self, val): + if val and isinstance(val, (list, tuple)): + self._locked = ':'.join(map(str, val)) + else: + self._locked = None + + @hybrid_property + def changeset_cache(self): + from kallithea.lib.vcs.backends.base import EmptyChangeset + dummy = EmptyChangeset().__json__() + if not self._changeset_cache: + return dummy + try: + return json.loads(self._changeset_cache) + except TypeError: + return dummy + + @changeset_cache.setter + def changeset_cache(self, val): + try: + self._changeset_cache = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def normalize_repo_name(cls, repo_name): + """ + Normalizes os specific repo_name to the format internally stored inside + dabatabase using URL_SEP + + :param cls: + :param repo_name: + """ + return cls.url_sep().join(repo_name.split(os.sep)) + + @classmethod + def get_by_repo_name(cls, repo_name): + q = Session().query(cls).filter(cls.repo_name == repo_name) + q = q.options(joinedload(Repository.fork))\ + .options(joinedload(Repository.user))\ + .options(joinedload(Repository.group)) + return q.scalar() + + @classmethod + def get_by_full_path(cls, repo_full_path): + repo_name = repo_full_path.split(cls.base_path(), 1)[-1] + repo_name = cls.normalize_repo_name(repo_name) + return cls.get_by_repo_name(repo_name.strip(URL_SEP)) + + @classmethod + def get_repo_forks(cls, repo_id): + return cls.query().filter(Repository.fork_id == repo_id) + + @classmethod + def base_path(cls): + """ + Returns base path when all repos are stored + + :param cls: + """ + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def forks(self): + """ + Return forks of this repo + """ + return Repository.get_repo_forks(self.repo_id) + + @property + def parent(self): + """ + Returns fork parent + """ + return self.fork + + @property + def just_name(self): + return self.repo_name.split(Repository.url_sep())[-1] + + @property + def groups_with_parents(self): + groups = [] + if self.group is None: + return groups + + cur_gr = self.group + groups.insert(0, cur_gr) + while 1: + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + groups.insert(0, gr) + + return groups + + @property + def groups_and_repo(self): + return self.groups_with_parents, self.just_name, self.repo_name + + @LazyProperty + def repo_path(self): + """ + Returns base full path for that repository means where it actually + exists on a filesystem + """ + q = Session().query(Ui).filter(Ui.ui_key == + Repository.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def repo_full_path(self): + p = [self.repo_path] + # we need to split the name by / since this is how we store the + # names in the database, but that eventually needs to be converted + # into a valid system path + p += self.repo_name.split(Repository.url_sep()) + return os.path.join(*map(safe_unicode, p)) + + @property + def cache_keys(self): + """ + Returns associated cache keys for that repo + """ + return CacheInvalidation.query()\ + .filter(CacheInvalidation.cache_args == self.repo_name)\ + .order_by(CacheInvalidation.cache_key)\ + .all() + + def get_new_name(self, repo_name): + """ + returns new full repository name based on assigned group and new new + + :param group_name: + """ + path_prefix = self.group.full_path_splitted if self.group else [] + return Repository.url_sep().join(path_prefix + [repo_name]) + + @property + def _ui(self): + """ + Creates an db based ui object for this repository + """ + from kallithea.lib.utils import make_ui + return make_ui('db', clear_session=False) + + @classmethod + def is_valid(cls, repo_name): + """ + returns True if given repo name is a valid filesystem repository + + :param cls: + :param repo_name: + """ + from kallithea.lib.utils import is_valid_repo + + return is_valid_repo(repo_name, cls.base_path()) + + def get_api_data(self): + """ + Common function for generating repo api data + + """ + repo = self + data = dict( + repo_id=repo.repo_id, + repo_name=repo.repo_name, + repo_type=repo.repo_type, + clone_uri=repo.clone_uri, + private=repo.private, + created_on=repo.created_on, + description=repo.description, + landing_rev=repo.landing_rev, + owner=repo.user.username, + fork_of=repo.fork.repo_name if repo.fork else None, + enable_statistics=repo.enable_statistics, + enable_locking=repo.enable_locking, + enable_downloads=repo.enable_downloads, + last_changeset=repo.changeset_cache, + locked_by=User.get(self.locked[0]).get_api_data() \ + if self.locked[0] else None, + locked_date=time_to_datetime(self.locked[1]) \ + if self.locked[1] else None + ) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) + if repository_fields: + for f in self.extra_fields: + data[f.field_key_prefixed] = f.field_value + + return data + + @classmethod + def lock(cls, repo, user_id, lock_time=None): + if not lock_time: + lock_time = time.time() + repo.locked = [user_id, lock_time] + Session().add(repo) + Session().commit() + + @classmethod + def unlock(cls, repo): + repo.locked = None + Session().add(repo) + Session().commit() + + @classmethod + def getlock(cls, repo): + return repo.locked + + @property + def last_db_change(self): + return self.updated_on + + def clone_url(self, **override): + from pylons import url + from urlparse import urlparse + import urllib + parsed_url = urlparse(url('home', qualified=True)) + default_clone_uri = '%(scheme)s://%(user)s%(pass)s%(netloc)s%(prefix)s%(path)s' + decoded_path = safe_unicode(urllib.unquote(parsed_url.path)) + args = { + 'user': '', + 'pass': '', + 'scheme': parsed_url.scheme, + 'netloc': parsed_url.netloc, + 'prefix': decoded_path, + 'path': self.repo_name + } + + args.update(override) + return default_clone_uri % args + + #========================================================================== + # SCM PROPERTIES + #========================================================================== + + def get_changeset(self, rev=None): + return get_changeset_safe(self.scm_instance, rev) + + def get_landing_changeset(self): + """ + Returns landing changeset, or if that doesn't exist returns the tip + """ + cs = self.get_changeset(self.landing_rev) or self.get_changeset() + return cs + + def update_changeset_cache(self, cs_cache=None): + """ + Update cache of last changeset for repository, keys should be:: + + short_id + raw_id + revision + message + date + author + + :param cs_cache: + """ + from kallithea.lib.vcs.backends.base import BaseChangeset + if cs_cache is None: + cs_cache = EmptyChangeset() + # use no-cache version here + scm_repo = self.scm_instance_no_cache() + if scm_repo: + cs_cache = scm_repo.get_changeset() + + if isinstance(cs_cache, BaseChangeset): + cs_cache = cs_cache.__json__() + + if (cs_cache != self.changeset_cache or not self.changeset_cache): + _default = datetime.datetime.fromtimestamp(0) + last_change = cs_cache.get('date') or _default + log.debug('updated repo %s with new cs cache %s' + % (self.repo_name, cs_cache)) + self.updated_on = last_change + self.changeset_cache = cs_cache + Session().add(self) + Session().commit() + else: + log.debug('Skipping repo:%s already with latest changes' + % self.repo_name) + + @property + def tip(self): + return self.get_changeset('tip') + + @property + def author(self): + return self.tip.author + + @property + def last_change(self): + return self.scm_instance.last_change + + def get_comments(self, revisions=None): + """ + Returns comments for this repository grouped by revisions + + :param revisions: filter query by revisions only + """ + cmts = ChangesetComment.query()\ + .filter(ChangesetComment.repo == self) + if revisions: + cmts = cmts.filter(ChangesetComment.revision.in_(revisions)) + grouped = collections.defaultdict(list) + for cmt in cmts.all(): + grouped[cmt.revision].append(cmt) + return grouped + + def statuses(self, revisions=None): + """ + Returns statuses for this repository + + :param revisions: list of revisions to get statuses for + """ + + statuses = ChangesetStatus.query()\ + .filter(ChangesetStatus.repo == self)\ + .filter(ChangesetStatus.version == 0) + if revisions: + statuses = statuses.filter(ChangesetStatus.revision.in_(revisions)) + grouped = {} + + #maybe we have open new pullrequest without a status ? + stat = ChangesetStatus.STATUS_UNDER_REVIEW + status_lbl = ChangesetStatus.get_status_lbl(stat) + for pr in PullRequest.query().filter(PullRequest.org_repo == self).all(): + for rev in pr.revisions: + pr_id = pr.pull_request_id + pr_repo = pr.other_repo.repo_name + grouped[rev] = [stat, status_lbl, pr_id, pr_repo] + + for stat in statuses.all(): + pr_id = pr_repo = None + if stat.pull_request: + pr_id = stat.pull_request.pull_request_id + pr_repo = stat.pull_request.other_repo.repo_name + grouped[stat.revision] = [str(stat.status), stat.status_lbl, + pr_id, pr_repo] + return grouped + + def _repo_size(self): + from kallithea.lib import helpers as h + log.debug('calculating repository size...') + return h.format_byte_size(self.scm_instance.size) + + #========================================================================== + # SCM CACHE INSTANCE + #========================================================================== + + def set_invalidate(self): + """ + Mark caches of this repo as invalid. + """ + CacheInvalidation.set_invalidate(self.repo_name) + + def scm_instance_no_cache(self): + return self.__get_instance() + + @property + def scm_instance(self): + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) + if full_cache: + return self.scm_instance_cached() + return self.__get_instance() + + def scm_instance_cached(self, valid_cache_keys=None): + @cache_region('long_term') + def _c(repo_name): + return self.__get_instance() + rn = self.repo_name + + valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys) + if not valid: + log.debug('Cache for %s invalidated, getting new object' % (rn)) + region_invalidate(_c, None, rn) + else: + log.debug('Getting obj for %s from cache' % (rn)) + return _c(rn) + + def __get_instance(self): + repo_full_path = self.repo_full_path + try: + alias = get_scm(repo_full_path)[0] + log.debug('Creating instance of %s repository from %s' + % (alias, repo_full_path)) + backend = get_backend(alias) + except VCSError: + log.error(traceback.format_exc()) + log.error('Perhaps this repository is in db and not in ' + 'filesystem run rescan repositories with ' + '"destroy old data " option from admin panel') + return + + if alias == 'hg': + + repo = backend(safe_str(repo_full_path), create=False, + baseui=self._ui) + # skip hidden web repository + if repo._get_hidden(): + return + else: + repo = backend(repo_full_path, create=False) + + return repo + + +class RepoGroup(Base, BaseModel): + __tablename__ = 'groups' + __table_args__ = ( + UniqueConstraint('group_name', 'group_parent_id'), + CheckConstraint('group_id != group_parent_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + __mapper_args__ = {'order_by': 'group_name'} + + group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + group_name = Column("group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) + group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + + repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + parent_group = relationship('RepoGroup', remote_side=group_id) + user = relationship('User') + + def __init__(self, group_name='', parent_group=None): + self.group_name = group_name + self.parent_group = parent_group + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id, + self.group_name) + + @classmethod + def groups_choices(cls, groups=None, show_empty_group=True): + from webhelpers.html import literal as _literal + if not groups: + groups = cls.query().all() + + repo_groups = [] + if show_empty_group: + repo_groups = [('-1', u'-- %s --' % _('top level'))] + sep = ' » ' + _name = lambda k: _literal(sep.join(k)) + + repo_groups.extend([(x.group_id, _name(x.full_path_splitted)) + for x in groups]) + + repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0]) + return repo_groups + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): + if case_insensitive: + gr = cls.query()\ + .filter(cls.group_name.ilike(group_name)) + else: + gr = cls.query()\ + .filter(cls.group_name == group_name) + if cache: + gr = gr.options(FromCache( + "sql_cache_short", + "get_group_%s" % _hash_key(group_name) + ) + ) + return gr.scalar() + + @property + def parents(self): + parents_recursion_limit = 5 + groups = [] + if self.parent_group is None: + return groups + cur_gr = self.parent_group + groups.insert(0, cur_gr) + cnt = 0 + while 1: + cnt += 1 + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + if cnt == parents_recursion_limit: + # this will prevent accidental infinit loops + log.error('group nested more than %s' % + parents_recursion_limit) + break + + groups.insert(0, gr) + return groups + + @property + def children(self): + return RepoGroup.query().filter(RepoGroup.parent_group == self) + + @property + def name(self): + return self.group_name.split(RepoGroup.url_sep())[-1] + + @property + def full_path(self): + return self.group_name + + @property + def full_path_splitted(self): + return self.group_name.split(RepoGroup.url_sep()) + + @property + def repositories(self): + return Repository.query()\ + .filter(Repository.group == self)\ + .order_by(Repository.repo_name) + + @property + def repositories_recursive_count(self): + cnt = self.repositories.count() + + def children_count(group): + cnt = 0 + for child in group.children: + cnt += child.repositories.count() + cnt += children_count(child) + return cnt + + return cnt + children_count(self) + + def _recursive_objects(self, include_repos=True): + all_ = [] + + def _get_members(root_gr): + if include_repos: + for r in root_gr.repositories: + all_.append(r) + childs = root_gr.children.all() + if childs: + for gr in childs: + all_.append(gr) + _get_members(gr) + + _get_members(self) + return [self] + all_ + + def recursive_groups_and_repos(self): + """ + Recursive return all groups, with repositories in those groups + """ + return self._recursive_objects() + + def recursive_groups(self): + """ + Returns all children groups for this group including children of children + """ + return self._recursive_objects(include_repos=False) + + def get_new_name(self, group_name): + """ + returns new full group name based on parent and new name + + :param group_name: + """ + path_prefix = (self.parent_group.full_path_splitted if + self.parent_group else []) + return RepoGroup.url_sep().join(path_prefix + [group_name]) + + def get_api_data(self): + """ + Common function for generating api data + + """ + group = self + data = dict( + group_id=group.group_id, + group_name=group.group_name, + group_description=group.group_description, + parent_group=group.parent_group.group_name if group.parent_group else None, + repositories=[x.repo_name for x in group.repositories], + owner=group.user.username + ) + return data + + +class Permission(Base, BaseModel): + __tablename__ = 'permissions' + __table_args__ = ( + Index('p_perm_name_idx', 'permission_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PERMS = [ + ('hg.admin', _('Kallithea Administrator')), + + ('repository.none', _('Repository no access')), + ('repository.read', _('Repository read access')), + ('repository.write', _('Repository write access')), + ('repository.admin', _('Repository admin access')), + + ('group.none', _('Repository group no access')), + ('group.read', _('Repository group read access')), + ('group.write', _('Repository group write access')), + ('group.admin', _('Repository group admin access')), + + ('usergroup.none', _('User group no access')), + ('usergroup.read', _('User group read access')), + ('usergroup.write', _('User group write access')), + ('usergroup.admin', _('User group admin access')), + + ('hg.repogroup.create.false', _('Repository Group creation disabled')), + ('hg.repogroup.create.true', _('Repository Group creation enabled')), + + ('hg.usergroup.create.false', _('User Group creation disabled')), + ('hg.usergroup.create.true', _('User Group creation enabled')), + + ('hg.create.none', _('Repository creation disabled')), + ('hg.create.repository', _('Repository creation enabled')), + + ('hg.fork.none', _('Repository forking disabled')), + ('hg.fork.repository', _('Repository forking enabled')), + + ('hg.register.none', _('Registration disabled')), + ('hg.register.manual_activate', _('User Registration with manual account activation')), + ('hg.register.auto_activate', _('User Registration with automatic account activation')), + + ('hg.extern_activate.manual', _('Manual activation of external account')), + ('hg.extern_activate.auto', _('Automatic activation of external account')), + + ] + + #definition of system default permissions for DEFAULT user + DEFAULT_USER_PERMISSIONS = [ + 'repository.read', + 'group.read', + 'usergroup.read', + 'hg.create.repository', + 'hg.fork.repository', + 'hg.register.manual_activate', + 'hg.extern_activate.auto', + ] + + # defines which permissions are more important higher the more important + # Weight defines which permissions are more important. + # The higher number the more important. + PERM_WEIGHTS = { + 'repository.none': 0, + 'repository.read': 1, + 'repository.write': 3, + 'repository.admin': 4, + + 'group.none': 0, + 'group.read': 1, + 'group.write': 3, + 'group.admin': 4, + + 'usergroup.none': 0, + 'usergroup.read': 1, + 'usergroup.write': 3, + 'usergroup.admin': 4, + 'hg.repogroup.create.false': 0, + 'hg.repogroup.create.true': 1, + + 'hg.usergroup.create.false': 0, + 'hg.usergroup.create.true': 1, + + 'hg.fork.none': 0, + 'hg.fork.repository': 1, + 'hg.create.none': 0, + 'hg.create.repository': 1 + } + + permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, self.permission_id, self.permission_name + ) + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.permission_name == key).scalar() + + @classmethod + def get_default_perms(cls, default_user_id): + q = Session().query(UserRepoToPerm, Repository, cls)\ + .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ + .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_group_perms(cls, default_user_id): + q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\ + .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\ + .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoGroupToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_user_group_perms(cls, default_user_id): + q = Session().query(UserUserGroupToPerm, UserGroup, cls)\ + .join((UserGroup, UserUserGroupToPerm.user_group_id == UserGroup.users_group_id))\ + .join((cls, UserUserGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserUserGroupToPerm.user_id == default_user_id) + + return q.all() + + +class UserRepoToPerm(Base, BaseModel): + __tablename__ = 'repo_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'repository_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + repository = relationship('Repository') + permission = relationship('Permission') + + @classmethod + def create(cls, user, repository, permission): + n = cls() + n.user = user + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.repository) + + +class UserUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'user_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + user_group = relationship('UserGroup') + permission = relationship('Permission') + + @classmethod + def create(cls, user, user_group, permission): + n = cls() + n.user = user + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.user_group) + + +class UserToPerm(Base, BaseModel): + __tablename__ = 'user_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + permission = relationship('Permission', lazy='joined') + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.permission) + + +class UserGroupRepoToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_to_perm' + __table_args__ = ( + UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + repository = relationship('Repository') + + @classmethod + def create(cls, users_group, repository, permission): + n = cls() + n.users_group = users_group + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.users_group, self.repository) + + +class UserGroupUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_group_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'), + CheckConstraint('target_user_group_id != user_group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id') + user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id') + permission = relationship('Permission') + + @classmethod + def create(cls, target_user_group, user_group, permission): + n = cls() + n.target_user_group = target_user_group + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.target_user_group, self.user_group) + + +class UserGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'permission_id',), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + + +class UserRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'user_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + group = relationship('RepoGroup') + permission = relationship('Permission') + + +class UserGroupRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + group = relationship('RepoGroup') + + +class Statistics(Base, BaseModel): + __tablename__ = 'statistics' + __table_args__ = ( + UniqueConstraint('repository_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) + stat_on_revision = Column("stat_on_revision", Integer(), nullable=False) + commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data + commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data + languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data + + repository = relationship('Repository', single_parent=True) + + +class UserFollowing(Base, BaseModel): + __tablename__ = 'user_followings' + __table_args__ = ( + UniqueConstraint('user_id', 'follows_repository_id'), + UniqueConstraint('user_id', 'follows_user_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None) + follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + + user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') + + follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') + follows_repository = relationship('Repository', order_by='Repository.repo_name') + + @classmethod + def get_repo_followers(cls, repo_id): + return cls.query().filter(cls.follows_repo_id == repo_id) + + +class CacheInvalidation(Base, BaseModel): + __tablename__ = 'cache_invalidation' + __table_args__ = ( + UniqueConstraint('cache_key'), + Index('key_idx', 'cache_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + # cache_id, not used + cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + # cache_key as created by _get_cache_key + cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # cache_args is a repo_name + cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # instance sets cache_active True when it is caching, + # other instances set cache_active to False to indicate that this cache is invalid + cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False) + + def __init__(self, cache_key, repo_name=''): + self.cache_key = cache_key + self.cache_args = repo_name + self.cache_active = False + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % (self.__class__.__name__, + self.cache_id, self.cache_key, self.cache_active) + + def _cache_key_partition(self): + prefix, repo_name, suffix = self.cache_key.partition(self.cache_args) + return prefix, repo_name, suffix + + def get_prefix(self): + """ + get prefix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[0] + + def get_suffix(self): + """ + get suffix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[2] + + @classmethod + def clear_cache(cls): + """ + Delete all cache keys from database. + Should only be run when all instances are down and all entries thus stale. + """ + cls.query().delete() + Session().commit() + + @classmethod + def _get_cache_key(cls, key): + """ + Wrapper for generating a unique cache key for this instance and "key". + key must / will start with a repo_name which will be stored in .cache_args . + """ + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') + return "%s%s" % (prefix, key) + + @classmethod + def set_invalidate(cls, repo_name): + """ + Mark all caches of a repo as invalid in the database. + """ + inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all() + + try: + for inv_obj in inv_objs: + log.debug('marking %s key for invalidation based on repo_name=%s' + % (inv_obj, safe_str(repo_name))) + inv_obj.cache_active = False + Session().add(inv_obj) + Session().commit() + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + + @classmethod + def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None): + """ + Mark this cache key as active and currently cached. + Return True if the existing cache registration still was valid. + Return False to indicate that it had been invalidated and caches should be refreshed. + """ + + key = (repo_name + '_' + kind) if kind else repo_name + cache_key = cls._get_cache_key(key) + + if valid_cache_keys and cache_key in valid_cache_keys: + return True + + try: + inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar() + if not inv_obj: + inv_obj = CacheInvalidation(cache_key, repo_name) + was_valid = inv_obj.cache_active + inv_obj.cache_active = True + Session().add(inv_obj) + Session().commit() + return was_valid + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + return False + + @classmethod + def get_valid_cache_keys(cls): + """ + Return opaque object with information of which caches still are valid + and can be used without checking for invalidation. + """ + return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all()) + + +class ChangesetComment(Base, BaseModel): + __tablename__ = 'changeset_comments' + __table_args__ = ( + Index('cc_revision_idx', 'revision'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + revision = Column('revision', String(40), nullable=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + line_no = Column('line_no', Unicode(10), nullable=True) + hl_lines = Column('hl_lines', Unicode(512), nullable=True) + f_path = Column('f_path', Unicode(1000), nullable=True) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) + text = Column('text', UnicodeText(25000), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan") + pull_request = relationship('PullRequest', lazy='joined') + + @classmethod + def get_users(cls, revision=None, pull_request_id=None): + """ + Returns user associated with this ChangesetComment. ie those + who actually commented + + :param cls: + :param revision: + """ + q = Session().query(User)\ + .join(ChangesetComment.author) + if revision: + q = q.filter(cls.revision == revision) + elif pull_request_id: + q = q.filter(cls.pull_request_id == pull_request_id) + return q.all() + + +class ChangesetStatus(Base, BaseModel): + __tablename__ = 'changeset_statuses' + __table_args__ = ( + Index('cs_revision_idx', 'revision'), + Index('cs_version_idx', 'version'), + UniqueConstraint('repo_id', 'revision', 'version'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed' + STATUS_APPROVED = 'approved' + STATUS_REJECTED = 'rejected' + STATUS_UNDER_REVIEW = 'under_review' + + STATUSES = [ + (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default + (STATUS_APPROVED, _("Approved")), + (STATUS_REJECTED, _("Rejected")), + (STATUS_UNDER_REVIEW, _("Under Review")), + ] + + changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + revision = Column('revision', String(40), nullable=False) + status = Column('status', String(128), nullable=False, default=DEFAULT) + changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id')) + modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now) + version = Column('version', Integer(), nullable=False, default=0) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + comment = relationship('ChangesetComment', lazy='joined') + pull_request = relationship('PullRequest', lazy='joined') + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, + self.status, self.author + ) + + @classmethod + def get_status_lbl(cls, value): + return dict(cls.STATUSES).get(value) + + @property + def status_lbl(self): + return ChangesetStatus.get_status_lbl(self.status) + + +class PullRequest(Base, BaseModel): + __tablename__ = 'pull_requests' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + # values for .status + STATUS_NEW = u'new' + STATUS_OPEN = u'open' + STATUS_CLOSED = u'closed' + + pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) + title = Column('title', Unicode(256), nullable=True) + description = Column('description', UnicodeText(10240), nullable=True) + status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW) # only for closedness, not approve/reject/etc + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max + org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + org_ref = Column('org_ref', Unicode(256), nullable=False) + other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + other_ref = Column('other_ref', Unicode(256), nullable=False) + + @hybrid_property + def revisions(self): + return self._revisions.split(':') + + @revisions.setter + def revisions(self, val): + self._revisions = ':'.join(val) + + @property + def org_ref_parts(self): + return self.org_ref.split(':') + + @property + def other_ref_parts(self): + return self.other_ref.split(':') + + author = relationship('User', lazy='joined') + reviewers = relationship('PullRequestReviewers', + cascade="all, delete, delete-orphan") + org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') + other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id') + statuses = relationship('ChangesetStatus') + comments = relationship('ChangesetComment', + cascade="all, delete, delete-orphan") + + def is_closed(self): + return self.status == self.STATUS_CLOSED + + @property + def last_review_status(self): + return self.statuses[-1].status if self.statuses else '' + + def __json__(self): + return dict( + revisions=self.revisions + ) + + +class PullRequestReviewers(Base, BaseModel): + __tablename__ = 'pull_request_reviewers' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + def __init__(self, user=None, pull_request=None): + self.user = user + self.pull_request = pull_request + + pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True) + + user = relationship('User') + pull_request = relationship('PullRequest') + + +class Notification(Base, BaseModel): + __tablename__ = 'notifications' + __table_args__ = ( + Index('notification_type_idx', 'type'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + TYPE_CHANGESET_COMMENT = u'cs_comment' + TYPE_MESSAGE = u'message' + TYPE_MENTION = u'mention' + TYPE_REGISTRATION = u'registration' + TYPE_PULL_REQUEST = u'pull_request' + TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' + + notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) + subject = Column('subject', Unicode(512), nullable=True) + body = Column('body', UnicodeText(50000), nullable=True) + created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + type_ = Column('type', Unicode(256)) + + created_by_user = relationship('User') + notifications_to_users = relationship('UserNotification', lazy='joined', + cascade="all, delete, delete-orphan") + + @property + def recipients(self): + return [x.user for x in UserNotification.query()\ + .filter(UserNotification.notification == self)\ + .order_by(UserNotification.user_id.asc()).all()] + + @classmethod + def create(cls, created_by, subject, body, recipients, type_=None): + if type_ is None: + type_ = Notification.TYPE_MESSAGE + + notification = cls() + notification.created_by_user = created_by + notification.subject = subject + notification.body = body + notification.type_ = type_ + notification.created_on = datetime.datetime.now() + + for u in recipients: + assoc = UserNotification() + assoc.notification = notification + u.notifications.append(assoc) + Session().add(notification) + return notification + + @property + def description(self): + from kallithea.model.notification import NotificationModel + return NotificationModel().make_description(self) + + +class UserNotification(Base, BaseModel): + __tablename__ = 'user_to_notification' + __table_args__ = ( + UniqueConstraint('user_id', 'notification_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True) + notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True) + read = Column('read', Boolean, default=False) + sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None) + + user = relationship('User', lazy="joined") + notification = relationship('Notification', lazy="joined", + order_by=lambda: Notification.created_on.desc(),) + + def mark_as_read(self): + self.read = True + Session().add(self) + + +class Gist(Base, BaseModel): + __tablename__ = 'gists' + __table_args__ = ( + Index('g_gist_access_id_idx', 'gist_access_id'), + Index('g_created_on_idx', 'created_on'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + GIST_PUBLIC = u'public' + GIST_PRIVATE = u'private' + + gist_id = Column('gist_id', Integer(), primary_key=True) + gist_access_id = Column('gist_access_id', Unicode(250)) + gist_description = Column('gist_description', UnicodeText(1024)) + gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True) + gist_expires = Column('gist_expires', Float(53), nullable=False) + gist_type = Column('gist_type', Unicode(128), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + owner = relationship('User') + + @classmethod + def get_or_404(cls, id_): + res = cls.query().filter(cls.gist_access_id == id_).scalar() + if not res: + raise HTTPNotFound + return res + + @classmethod + def get_by_access_id(cls, gist_access_id): + return cls.query().filter(cls.gist_access_id == gist_access_id).scalar() + + def gist_url(self): + import kallithea + alias_url = kallithea.CONFIG.get('gist_alias_url') + if alias_url: + return alias_url.replace('{gistid}', self.gist_access_id) + + from pylons import url + return url('gist', gist_id=self.gist_access_id, qualified=True) + + @classmethod + def base_path(cls): + """ + Returns base path when all gists are stored + + :param cls: + """ + from kallithea.model.gist import GIST_STORE_LOC + q = Session().query(Ui)\ + .filter(Ui.ui_key == URL_SEP) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return os.path.join(q.one().ui_value, GIST_STORE_LOC) + + def get_api_data(self): + """ + Common function for generating gist related data for API + """ + gist = self + data = dict( + gist_id=gist.gist_id, + type=gist.gist_type, + access_id=gist.gist_access_id, + description=gist.gist_description, + url=gist.gist_url(), + expires=gist.gist_expires, + created_on=gist.created_on, + ) + return data + + def __json__(self): + data = dict( + ) + data.update(self.get_api_data()) + return data + ## SCM functions + + @property + def scm_instance(self): + from kallithea.lib.vcs import get_repo + base_path = self.base_path() + return get_repo(os.path.join(*map(safe_str, + [base_path, self.gist_access_id]))) + + +class DbMigrateVersion(Base, BaseModel): + __tablename__ = 'db_migrate_version' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + repository_id = Column('repository_id', String(250), primary_key=True) + repository_path = Column('repository_path', Text) + version = Column('version', Integer) diff --git a/kallithea/lib/dbmigrate/schema/db_2_0_0.py b/kallithea/lib/dbmigrate/schema/db_2_0_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/schema/db_2_0_0.py @@ -0,0 +1,2334 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.db +~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import os +import time +import logging +import datetime +import traceback +import hashlib +import collections +import functools + +from sqlalchemy import * +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import relationship, joinedload, class_mapper, validates +from sqlalchemy.exc import DatabaseError +from beaker.cache import cache_region, region_invalidate +from webob.exc import HTTPNotFound + +from pylons.i18n.translation import lazy_ugettext as _ + +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset + +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ + safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache + +from kallithea.model.meta import Base, Session + +URL_SEP = '/' +log = logging.getLogger(__name__) + +from kallithea import DB_PREFIX + +#============================================================================== +# BASE CLASSES +#============================================================================== + +_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest() + + +class BaseModel(object): + """ + Base Model for all classess + """ + + @classmethod + def _get_keys(cls): + """return column names for this model """ + return class_mapper(cls).c.keys() + + def get_dict(self): + """ + return dict with keys and values corresponding + to this model data """ + + d = {} + for k in self._get_keys(): + d[k] = getattr(self, k) + + # also use __json__() if present to get additional fields + _json_attr = getattr(self, '__json__', None) + if _json_attr: + # update with attributes from __json__ + if callable(_json_attr): + _json_attr = _json_attr() + for k, val in _json_attr.iteritems(): + d[k] = val + return d + + def get_appstruct(self): + """return list with keys and values tupples corresponding + to this model data """ + + l = [] + for k in self._get_keys(): + l.append((k, getattr(self, k),)) + return l + + def populate_obj(self, populate_dict): + """populate model with data from given populate_dict""" + + for k in self._get_keys(): + if k in populate_dict: + setattr(self, k, populate_dict[k]) + + @classmethod + def query(cls): + return Session().query(cls) + + @classmethod + def get(cls, id_): + if id_: + return cls.query().get(id_) + + @classmethod + def get_or_404(cls, id_): + try: + id_ = int(id_) + except (TypeError, ValueError): + raise HTTPNotFound + + res = cls.query().get(id_) + if not res: + raise HTTPNotFound + return res + + @classmethod + def getAll(cls): + # deprecated and left for backward compatibility + return cls.get_all() + + @classmethod + def get_all(cls): + return cls.query().all() + + @classmethod + def delete(cls, id_): + obj = cls.query().get(id_) + Session().delete(obj) + + def __repr__(self): + if hasattr(self, '__unicode__'): + # python repr needs to return str + return safe_str(self.__unicode__()) + return '' % (self.__class__.__name__) + + +class Setting(Base, BaseModel): + SETTINGS_TYPES = { + 'str': safe_str, + 'int': safe_int, + 'unicode': safe_unicode, + 'bool': str2bool, + 'list': functools.partial(aslist, sep=',') + } + __tablename__ = DB_PREFIX + 'settings' + __table_args__ = ( + UniqueConstraint('app_settings_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + app_settings_name = Column("app_settings_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_value = Column("app_settings_value", String(4096, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_type = Column("app_settings_type", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __init__(self, key='', val='', type='unicode'): + self.app_settings_name = key + self.app_settings_value = val + self.app_settings_type = type + + @validates('_app_settings_value') + def validate_settings_value(self, key, val): + assert type(val) == unicode + return val + + @hybrid_property + def app_settings_value(self): + v = self._app_settings_value + _type = self.app_settings_type + converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode'] + return converter(v) + + @app_settings_value.setter + def app_settings_value(self, val): + """ + Setter that will always make sure we use unicode in app_settings_value + + :param val: + """ + self._app_settings_value = safe_unicode(val) + + @hybrid_property + def app_settings_type(self): + return self._app_settings_type + + @app_settings_type.setter + def app_settings_type(self, val): + if val not in self.SETTINGS_TYPES: + raise Exception('type must be one of %s got %s' + % (self.SETTINGS_TYPES.keys(), val)) + self._app_settings_type = val + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % ( + self.__class__.__name__, + self.app_settings_name, self.app_settings_value, self.app_settings_type + ) + + @classmethod + def get_by_name(cls, key): + return cls.query()\ + .filter(cls.app_settings_name == key).scalar() + + @classmethod + def get_by_name_or_create(cls, key, val='', type='unicode'): + res = cls.get_by_name(key) + if not res: + res = cls(key, val, type) + return res + + @classmethod + def create_or_update(cls, key, val=Optional(''), type=Optional('unicode')): + """ + Creates or updates Kallithea setting. If updates is triggered it will only + update parameters that are explicityl set Optional instance will be skipped + + :param key: + :param val: + :param type: + :return: + """ + res = cls.get_by_name(key) + if not res: + val = Optional.extract(val) + type = Optional.extract(type) + res = cls(key, val, type) + else: + res.app_settings_name = key + if not isinstance(val, Optional): + # update if set + res.app_settings_value = val + if not isinstance(type, Optional): + # update if set + res.app_settings_type = type + return res + + @classmethod + def get_app_settings(cls, cache=False): + + ret = cls.query() + + if cache: + ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) + + if not ret: + raise Exception('Could not get application settings !') + settings = {} + for each in ret: + settings[each.app_settings_name] = \ + each.app_settings_value + + return settings + + @classmethod + def get_auth_plugins(cls, cache=False): + auth_plugins = cls.get_by_name("auth_plugins").app_settings_value + return auth_plugins + + @classmethod + def get_auth_settings(cls, cache=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('auth_')).all() + fd = {} + for row in ret: + fd.update({row.app_settings_name: row.app_settings_value}) + + return fd + + @classmethod + def get_default_repo_settings(cls, cache=False, strip_prefix=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('default_')).all() + fd = {} + for row in ret: + key = row.app_settings_name + if strip_prefix: + key = remove_prefix(key, prefix='default_') + fd.update({key: row.app_settings_value}) + + return fd + + @classmethod + def get_server_info(cls): + import pkg_resources + import platform + import kallithea + from kallithea.lib.utils import check_git_version + mods = [(p.project_name, p.version) for p in pkg_resources.working_set] + info = { + 'modules': sorted(mods, key=lambda k: k[0].lower()), + 'py_version': platform.python_version(), + 'platform': platform.platform(), + 'kallithea_version': kallithea.__version__, + 'git_version': str(check_git_version()), + 'git_path': kallithea.CONFIG.get('git_path') + } + return info + + +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' + __table_args__ = ( + UniqueConstraint('ui_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + HOOK_UPDATE = 'changegroup.update' + HOOK_REPO_SIZE = 'changegroup.repo_size' + HOOK_PUSH = 'changegroup.push_logger' + HOOK_PRE_PUSH = 'prechangegroup.pre_push' + HOOK_PULL = 'outgoing.pull_logger' + HOOK_PRE_PULL = 'preoutgoing.pre_pull' + + ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) + + # def __init__(self, section='', key='', value=''): + # self.ui_section = section + # self.ui_key = key + # self.ui_value = value + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.ui_key == key).scalar() + + @classmethod + def get_builtin_hooks(cls): + q = cls.query() + q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + return q.all() + + @classmethod + def get_custom_hooks(cls): + q = cls.query() + q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + q = q.filter(cls.ui_section == 'hooks') + return q.all() + + @classmethod + def get_repos_location(cls): + return cls.get_by_key('/').ui_value + + @classmethod + def create_or_update_hook(cls, key, val): + new_ui = cls.get_by_key(key) or cls() + new_ui.ui_section = 'hooks' + new_ui.ui_active = True + new_ui.ui_key = key + new_ui.ui_value = val + + Session().add(new_ui) + + def __repr__(self): + return '' % (self.__class__.__name__, self.ui_key, + self.ui_value) + + +class User(Base, BaseModel): + __tablename__ = 'users' + __table_args__ = ( + UniqueConstraint('username'), UniqueConstraint('email'), + Index('u_username_idx', 'username'), + Index('u_email_idx', 'email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + DEFAULT_USER = 'default' + + user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + admin = Column("admin", Boolean(), nullable=True, unique=None, default=False) + name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) + extern_type = Column("extern_type", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + extern_name = Column("extern_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + #for migration reasons, this is going to be later deleted + ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + user_log = relationship('UserLog') + user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') + + repositories = relationship('Repository') + user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all') + followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all') + + repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all') + repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all') + + group_member = relationship('UserGroupMember', cascade='all') + + notifications = relationship('UserNotification', cascade='all') + # notifications assigned to this user + user_created_notifications = relationship('Notification', cascade='all') + # comments created by this user + user_comments = relationship('ChangesetComment', cascade='all') + #extra emails for this user + user_emails = relationship('UserEmailMap', cascade='all') + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + @property + def firstname(self): + # alias for future + return self.name + + @property + def emails(self): + other = UserEmailMap.query().filter(UserEmailMap.user==self).all() + return [self.email] + [x.email for x in other] + + @property + def ip_addresses(self): + ret = UserIpMap.query().filter(UserIpMap.user == self).all() + return [x.ip_addr for x in ret] + + @property + def username_and_name(self): + return '%s (%s %s)' % (self.username, self.firstname, self.lastname) + + @property + def full_name(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def full_name_or_username(self): + return ('%s %s' % (self.firstname, self.lastname) + if (self.firstname and self.lastname) else self.username) + + @property + def full_contact(self): + return '%s %s <%s>' % (self.firstname, self.lastname, self.email) + + @property + def short_contact(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def is_admin(self): + return self.admin + + @property + def AuthUser(self): + """ + Returns instance of AuthUser for this user + """ + from kallithea.lib.auth import AuthUser + return AuthUser(user_id=self.user_id, api_key=self.api_key, + username=self.username) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.user_id, self.username) + + @classmethod + def get_by_username(cls, username, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.username.ilike(username)) + else: + q = cls.query().filter(cls.username == username) + + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(username) + ) + ) + return q.scalar() + + @classmethod + def get_by_api_key(cls, api_key, cache=False): + q = cls.query().filter(cls.api_key == api_key) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_api_key_%s" % api_key)) + return q.scalar() + + @classmethod + def get_by_email(cls, email, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.email.ilike(email)) + else: + q = cls.query().filter(cls.email == email) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_key_%s" % email)) + + ret = q.scalar() + if ret is None: + q = UserEmailMap.query() + # try fetching in alternate email map + if case_insensitive: + q = q.filter(UserEmailMap.email.ilike(email)) + else: + q = q.filter(UserEmailMap.email == email) + q = q.options(joinedload(UserEmailMap.user)) + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_map_key_%s" % email)) + ret = getattr(q.scalar(), 'user', None) + + return ret + + @classmethod + def get_from_cs_author(cls, author): + """ + Tries to get User objects out of commit author string + + :param author: + """ + from kallithea.lib.helpers import email, author_name + # Valid email in the attribute passed, see if they're in the system + _email = email(author) + if _email: + user = cls.get_by_email(_email, case_insensitive=True) + if user: + return user + # Maybe we can match by username? + _author = author_name(author) + user = cls.get_by_username(_author, case_insensitive=True) + if user: + return user + + def update_lastlogin(self): + """Update user lastlogin""" + self.last_login = datetime.datetime.now() + Session().add(self) + log.debug('updated user %s lastlogin' % self.username) + + @classmethod + def get_first_admin(cls): + user = User.query().filter(User.admin == True).first() + if user is None: + raise Exception('Missing administrative account!') + return user + + @classmethod + def get_default_user(cls, cache=False): + user = User.get_by_username(User.DEFAULT_USER, cache=cache) + if user is None: + raise Exception('Missing default account!') + return user + + def get_api_data(self): + """ + Common function for generating user related data for API + """ + user = self + data = dict( + user_id=user.user_id, + username=user.username, + firstname=user.name, + lastname=user.lastname, + email=user.email, + emails=user.emails, + api_key=user.api_key, + active=user.active, + admin=user.admin, + extern_type=user.extern_type, + extern_name=user.extern_name, + last_login=user.last_login, + ip_addresses=user.ip_addresses + ) + return data + + def __json__(self): + data = dict( + full_name=self.full_name, + full_name_or_username=self.full_name_or_username, + short_contact=self.short_contact, + full_contact=self.full_contact + ) + data.update(self.get_api_data()) + return data + + +class UserEmailMap(Base, BaseModel): + __tablename__ = 'user_email_map' + __table_args__ = ( + Index('uem_email_idx', 'email'), + UniqueConstraint('email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + user = relationship('User', lazy='joined') + + @validates('_email') + def validate_email(self, key, email): + # check if this email is not main one + main_email = Session().query(User).filter(User.email == email).scalar() + if main_email is not None: + raise AttributeError('email %s is present is user table' % email) + return email + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + +class UserIpMap(Base, BaseModel): + __tablename__ = 'user_ip_map' + __table_args__ = ( + UniqueConstraint('user_id', 'ip_addr'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + user = relationship('User', lazy='joined') + + @classmethod + def _get_ip_range(cls, ip_addr): + from kallithea.lib import ipaddr + net = ipaddr.IPNetwork(address=ip_addr) + return [str(net.network), str(net.broadcast)] + + def __json__(self): + return dict( + ip_addr=self.ip_addr, + ip_range=self._get_ip_range(self.ip_addr) + ) + + +class UserLog(Base, BaseModel): + __tablename__ = 'user_logs' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True) + repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.repository_name, + self.action) + + @property + def action_as_day(self): + return datetime.date(*self.action_date.timetuple()[:3]) + + user = relationship('User') + repository = relationship('Repository', cascade='') + + +class UserGroup(Base, BaseModel): + __tablename__ = 'users_groups' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + user_group_description = Column("user_group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + # don't trigger lazy load for migrations + #members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined") + users_group_to_perm = relationship('UserGroupToPerm', cascade='all') + users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all') + user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all') + + user = relationship('User') + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.users_group_id, + self.users_group_name) + + @classmethod + def get_by_group_name(cls, group_name, cache=False, + case_insensitive=False): + if case_insensitive: + q = cls.query().filter(cls.users_group_name.ilike(group_name)) + else: + q = cls.query().filter(cls.users_group_name == group_name) + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(group_name) + ) + ) + return q.scalar() + + @classmethod + def get(cls, user_group_id, cache=False): + user_group = cls.query() + if cache: + user_group = user_group.options(FromCache("sql_cache_short", + "get_users_group_%s" % user_group_id)) + return user_group.get(user_group_id) + + def get_api_data(self, with_members=True): + user_group = self + + data = dict( + users_group_id=user_group.users_group_id, + group_name=user_group.users_group_name, + group_description=user_group.user_group_description, + active=user_group.users_group_active, + owner=user_group.user.username, + ) + if with_members: + members = [] + for user in user_group.members: + user = user.user + members.append(user.get_api_data()) + data['members'] = members + + return data + + +class UserGroupMember(Base, BaseModel): + __tablename__ = 'users_groups_members' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + + user = relationship('User', lazy='joined') + users_group = relationship('UserGroup') + + def __init__(self, gr_id='', u_id=''): + self.users_group_id = gr_id + self.user_id = u_id + + +class RepositoryField(Base, BaseModel): + __tablename__ = 'repositories_fields' + __table_args__ = ( + UniqueConstraint('repository_id', 'field_key'), # no-multi field + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields + + repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + field_key = Column("field_key", String(250, convert_unicode=False, assert_unicode=None)) + field_label = Column("field_label", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_value = Column("field_value", String(10000, convert_unicode=False, assert_unicode=None), nullable=False) + field_desc = Column("field_desc", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_type = Column("field_type", String(256), nullable=False, unique=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repository = relationship('Repository') + + @property + def field_key_prefixed(self): + return 'ex_%s' % self.field_key + + @classmethod + def un_prefix_key(cls, key): + if key.startswith(cls.PREFIX): + return key[len(cls.PREFIX):] + return key + + @classmethod + def get_by_key_name(cls, key, repo): + row = cls.query()\ + .filter(cls.repository == repo)\ + .filter(cls.field_key == key).scalar() + return row + + +class Repository(Base, BaseModel): + __tablename__ = 'repositories' + __table_args__ = ( + UniqueConstraint('repo_name'), + Index('r_repo_name_idx', 'repo_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + private = Column("private", Boolean(), nullable=True, unique=None, default=None) + enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True) + enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True) + description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data + + fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) + + user = relationship('User') + fork = relationship('Repository', remote_side=repo_id) + group = relationship('RepoGroup') + repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + stats = relationship('Statistics', cascade='all', uselist=False) + + followers = relationship('UserFollowing', + primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', + cascade='all') + extra_fields = relationship('RepositoryField', + cascade="all, delete, delete-orphan") + + logs = relationship('UserLog') + comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan") + + pull_requests_org = relationship('PullRequest', + primaryjoin='PullRequest.org_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + pull_requests_other = relationship('PullRequest', + primaryjoin='PullRequest.other_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, + safe_unicode(self.repo_name)) + + @hybrid_property + def locked(self): + # always should return [user_id, timelocked] + if self._locked: + _lock_info = self._locked.split(':') + return int(_lock_info[0]), _lock_info[1] + return [None, None] + + @locked.setter + def locked(self, val): + if val and isinstance(val, (list, tuple)): + self._locked = ':'.join(map(str, val)) + else: + self._locked = None + + @hybrid_property + def changeset_cache(self): + from kallithea.lib.vcs.backends.base import EmptyChangeset + dummy = EmptyChangeset().__json__() + if not self._changeset_cache: + return dummy + try: + return json.loads(self._changeset_cache) + except TypeError: + return dummy + + @changeset_cache.setter + def changeset_cache(self, val): + try: + self._changeset_cache = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def normalize_repo_name(cls, repo_name): + """ + Normalizes os specific repo_name to the format internally stored inside + dabatabase using URL_SEP + + :param cls: + :param repo_name: + """ + return cls.url_sep().join(repo_name.split(os.sep)) + + @classmethod + def get_by_repo_name(cls, repo_name): + q = Session().query(cls).filter(cls.repo_name == repo_name) + q = q.options(joinedload(Repository.fork))\ + .options(joinedload(Repository.user))\ + .options(joinedload(Repository.group)) + return q.scalar() + + @classmethod + def get_by_full_path(cls, repo_full_path): + repo_name = repo_full_path.split(cls.base_path(), 1)[-1] + repo_name = cls.normalize_repo_name(repo_name) + return cls.get_by_repo_name(repo_name.strip(URL_SEP)) + + @classmethod + def get_repo_forks(cls, repo_id): + return cls.query().filter(Repository.fork_id == repo_id) + + @classmethod + def base_path(cls): + """ + Returns base path when all repos are stored + + :param cls: + """ + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def forks(self): + """ + Return forks of this repo + """ + return Repository.get_repo_forks(self.repo_id) + + @property + def parent(self): + """ + Returns fork parent + """ + return self.fork + + @property + def just_name(self): + return self.repo_name.split(Repository.url_sep())[-1] + + @property + def groups_with_parents(self): + groups = [] + if self.group is None: + return groups + + cur_gr = self.group + groups.insert(0, cur_gr) + while 1: + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + groups.insert(0, gr) + + return groups + + @property + def groups_and_repo(self): + return self.groups_with_parents, self.just_name, self.repo_name + + @LazyProperty + def repo_path(self): + """ + Returns base full path for that repository means where it actually + exists on a filesystem + """ + q = Session().query(Ui).filter(Ui.ui_key == + Repository.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def repo_full_path(self): + p = [self.repo_path] + # we need to split the name by / since this is how we store the + # names in the database, but that eventually needs to be converted + # into a valid system path + p += self.repo_name.split(Repository.url_sep()) + return os.path.join(*map(safe_unicode, p)) + + @property + def cache_keys(self): + """ + Returns associated cache keys for that repo + """ + return CacheInvalidation.query()\ + .filter(CacheInvalidation.cache_args == self.repo_name)\ + .order_by(CacheInvalidation.cache_key)\ + .all() + + def get_new_name(self, repo_name): + """ + returns new full repository name based on assigned group and new new + + :param group_name: + """ + path_prefix = self.group.full_path_splitted if self.group else [] + return Repository.url_sep().join(path_prefix + [repo_name]) + + @property + def _ui(self): + """ + Creates an db based ui object for this repository + """ + from kallithea.lib.utils import make_ui + return make_ui('db', clear_session=False) + + @classmethod + def is_valid(cls, repo_name): + """ + returns True if given repo name is a valid filesystem repository + + :param cls: + :param repo_name: + """ + from kallithea.lib.utils import is_valid_repo + + return is_valid_repo(repo_name, cls.base_path()) + + def get_api_data(self): + """ + Common function for generating repo api data + + """ + repo = self + data = dict( + repo_id=repo.repo_id, + repo_name=repo.repo_name, + repo_type=repo.repo_type, + clone_uri=repo.clone_uri, + private=repo.private, + created_on=repo.created_on, + description=repo.description, + landing_rev=repo.landing_rev, + owner=repo.user.username, + fork_of=repo.fork.repo_name if repo.fork else None, + enable_statistics=repo.enable_statistics, + enable_locking=repo.enable_locking, + enable_downloads=repo.enable_downloads, + last_changeset=repo.changeset_cache, + locked_by=User.get(self.locked[0]).get_api_data() \ + if self.locked[0] else None, + locked_date=time_to_datetime(self.locked[1]) \ + if self.locked[1] else None + ) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) + if repository_fields: + for f in self.extra_fields: + data[f.field_key_prefixed] = f.field_value + + return data + + @classmethod + def lock(cls, repo, user_id, lock_time=None): + if not lock_time: + lock_time = time.time() + repo.locked = [user_id, lock_time] + Session().add(repo) + Session().commit() + + @classmethod + def unlock(cls, repo): + repo.locked = None + Session().add(repo) + Session().commit() + + @classmethod + def getlock(cls, repo): + return repo.locked + + @property + def last_db_change(self): + return self.updated_on + + def clone_url(self, **override): + from pylons import url + from urlparse import urlparse + import urllib + parsed_url = urlparse(url('home', qualified=True)) + default_clone_uri = '%(scheme)s://%(user)s%(pass)s%(netloc)s%(prefix)s%(path)s' + decoded_path = safe_unicode(urllib.unquote(parsed_url.path)) + args = { + 'user': '', + 'pass': '', + 'scheme': parsed_url.scheme, + 'netloc': parsed_url.netloc, + 'prefix': decoded_path, + 'path': self.repo_name + } + + args.update(override) + return default_clone_uri % args + + #========================================================================== + # SCM PROPERTIES + #========================================================================== + + def get_changeset(self, rev=None): + return get_changeset_safe(self.scm_instance, rev) + + def get_landing_changeset(self): + """ + Returns landing changeset, or if that doesn't exist returns the tip + """ + cs = self.get_changeset(self.landing_rev) or self.get_changeset() + return cs + + def update_changeset_cache(self, cs_cache=None): + """ + Update cache of last changeset for repository, keys should be:: + + short_id + raw_id + revision + message + date + author + + :param cs_cache: + """ + from kallithea.lib.vcs.backends.base import BaseChangeset + if cs_cache is None: + cs_cache = EmptyChangeset() + # use no-cache version here + scm_repo = self.scm_instance_no_cache() + if scm_repo: + cs_cache = scm_repo.get_changeset() + + if isinstance(cs_cache, BaseChangeset): + cs_cache = cs_cache.__json__() + + if (cs_cache != self.changeset_cache or not self.changeset_cache): + _default = datetime.datetime.fromtimestamp(0) + last_change = cs_cache.get('date') or _default + log.debug('updated repo %s with new cs cache %s' + % (self.repo_name, cs_cache)) + self.updated_on = last_change + self.changeset_cache = cs_cache + Session().add(self) + Session().commit() + else: + log.debug('Skipping repo:%s already with latest changes' + % self.repo_name) + + @property + def tip(self): + return self.get_changeset('tip') + + @property + def author(self): + return self.tip.author + + @property + def last_change(self): + return self.scm_instance.last_change + + def get_comments(self, revisions=None): + """ + Returns comments for this repository grouped by revisions + + :param revisions: filter query by revisions only + """ + cmts = ChangesetComment.query()\ + .filter(ChangesetComment.repo == self) + if revisions: + cmts = cmts.filter(ChangesetComment.revision.in_(revisions)) + grouped = collections.defaultdict(list) + for cmt in cmts.all(): + grouped[cmt.revision].append(cmt) + return grouped + + def statuses(self, revisions=None): + """ + Returns statuses for this repository + + :param revisions: list of revisions to get statuses for + """ + + statuses = ChangesetStatus.query()\ + .filter(ChangesetStatus.repo == self)\ + .filter(ChangesetStatus.version == 0) + if revisions: + statuses = statuses.filter(ChangesetStatus.revision.in_(revisions)) + grouped = {} + + #maybe we have open new pullrequest without a status ? + stat = ChangesetStatus.STATUS_UNDER_REVIEW + status_lbl = ChangesetStatus.get_status_lbl(stat) + for pr in PullRequest.query().filter(PullRequest.org_repo == self).all(): + for rev in pr.revisions: + pr_id = pr.pull_request_id + pr_repo = pr.other_repo.repo_name + grouped[rev] = [stat, status_lbl, pr_id, pr_repo] + + for stat in statuses.all(): + pr_id = pr_repo = None + if stat.pull_request: + pr_id = stat.pull_request.pull_request_id + pr_repo = stat.pull_request.other_repo.repo_name + grouped[stat.revision] = [str(stat.status), stat.status_lbl, + pr_id, pr_repo] + return grouped + + def _repo_size(self): + from kallithea.lib import helpers as h + log.debug('calculating repository size...') + return h.format_byte_size(self.scm_instance.size) + + #========================================================================== + # SCM CACHE INSTANCE + #========================================================================== + + def set_invalidate(self): + """ + Mark caches of this repo as invalid. + """ + CacheInvalidation.set_invalidate(self.repo_name) + + def scm_instance_no_cache(self): + return self.__get_instance() + + @property + def scm_instance(self): + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) + if full_cache: + return self.scm_instance_cached() + return self.__get_instance() + + def scm_instance_cached(self, valid_cache_keys=None): + @cache_region('long_term') + def _c(repo_name): + return self.__get_instance() + rn = self.repo_name + + valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys) + if not valid: + log.debug('Cache for %s invalidated, getting new object' % (rn)) + region_invalidate(_c, None, rn) + else: + log.debug('Getting obj for %s from cache' % (rn)) + return _c(rn) + + def __get_instance(self): + repo_full_path = self.repo_full_path + try: + alias = get_scm(repo_full_path)[0] + log.debug('Creating instance of %s repository from %s' + % (alias, repo_full_path)) + backend = get_backend(alias) + except VCSError: + log.error(traceback.format_exc()) + log.error('Perhaps this repository is in db and not in ' + 'filesystem run rescan repositories with ' + '"destroy old data " option from admin panel') + return + + if alias == 'hg': + + repo = backend(safe_str(repo_full_path), create=False, + baseui=self._ui) + # skip hidden web repository + if repo._get_hidden(): + return + else: + repo = backend(repo_full_path, create=False) + + return repo + + +class RepoGroup(Base, BaseModel): + __tablename__ = 'groups' + __table_args__ = ( + UniqueConstraint('group_name', 'group_parent_id'), + CheckConstraint('group_id != group_parent_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + __mapper_args__ = {'order_by': 'group_name'} + + group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + group_name = Column("group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) + group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + + repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + parent_group = relationship('RepoGroup', remote_side=group_id) + user = relationship('User') + + def __init__(self, group_name='', parent_group=None): + self.group_name = group_name + self.parent_group = parent_group + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id, + self.group_name) + + @classmethod + def groups_choices(cls, groups=None, show_empty_group=True): + from webhelpers.html import literal as _literal + if not groups: + groups = cls.query().all() + + repo_groups = [] + if show_empty_group: + repo_groups = [('-1', u'-- %s --' % _('top level'))] + sep = ' » ' + _name = lambda k: _literal(sep.join(k)) + + repo_groups.extend([(x.group_id, _name(x.full_path_splitted)) + for x in groups]) + + repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0]) + return repo_groups + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): + if case_insensitive: + gr = cls.query()\ + .filter(cls.group_name.ilike(group_name)) + else: + gr = cls.query()\ + .filter(cls.group_name == group_name) + if cache: + gr = gr.options(FromCache( + "sql_cache_short", + "get_group_%s" % _hash_key(group_name) + ) + ) + return gr.scalar() + + @property + def parents(self): + parents_recursion_limit = 5 + groups = [] + if self.parent_group is None: + return groups + cur_gr = self.parent_group + groups.insert(0, cur_gr) + cnt = 0 + while 1: + cnt += 1 + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + if cnt == parents_recursion_limit: + # this will prevent accidental infinit loops + log.error('group nested more than %s' % + parents_recursion_limit) + break + + groups.insert(0, gr) + return groups + + @property + def children(self): + return RepoGroup.query().filter(RepoGroup.parent_group == self) + + @property + def name(self): + return self.group_name.split(RepoGroup.url_sep())[-1] + + @property + def full_path(self): + return self.group_name + + @property + def full_path_splitted(self): + return self.group_name.split(RepoGroup.url_sep()) + + @property + def repositories(self): + return Repository.query()\ + .filter(Repository.group == self)\ + .order_by(Repository.repo_name) + + @property + def repositories_recursive_count(self): + cnt = self.repositories.count() + + def children_count(group): + cnt = 0 + for child in group.children: + cnt += child.repositories.count() + cnt += children_count(child) + return cnt + + return cnt + children_count(self) + + def _recursive_objects(self, include_repos=True): + all_ = [] + + def _get_members(root_gr): + if include_repos: + for r in root_gr.repositories: + all_.append(r) + childs = root_gr.children.all() + if childs: + for gr in childs: + all_.append(gr) + _get_members(gr) + + _get_members(self) + return [self] + all_ + + def recursive_groups_and_repos(self): + """ + Recursive return all groups, with repositories in those groups + """ + return self._recursive_objects() + + def recursive_groups(self): + """ + Returns all children groups for this group including children of children + """ + return self._recursive_objects(include_repos=False) + + def get_new_name(self, group_name): + """ + returns new full group name based on parent and new name + + :param group_name: + """ + path_prefix = (self.parent_group.full_path_splitted if + self.parent_group else []) + return RepoGroup.url_sep().join(path_prefix + [group_name]) + + def get_api_data(self): + """ + Common function for generating api data + + """ + group = self + data = dict( + group_id=group.group_id, + group_name=group.group_name, + group_description=group.group_description, + parent_group=group.parent_group.group_name if group.parent_group else None, + repositories=[x.repo_name for x in group.repositories], + owner=group.user.username + ) + return data + + +class Permission(Base, BaseModel): + __tablename__ = 'permissions' + __table_args__ = ( + Index('p_perm_name_idx', 'permission_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PERMS = [ + ('hg.admin', _('Kallithea Administrator')), + + ('repository.none', _('Repository no access')), + ('repository.read', _('Repository read access')), + ('repository.write', _('Repository write access')), + ('repository.admin', _('Repository admin access')), + + ('group.none', _('Repository group no access')), + ('group.read', _('Repository group read access')), + ('group.write', _('Repository group write access')), + ('group.admin', _('Repository group admin access')), + + ('usergroup.none', _('User group no access')), + ('usergroup.read', _('User group read access')), + ('usergroup.write', _('User group write access')), + ('usergroup.admin', _('User group admin access')), + + ('hg.repogroup.create.false', _('Repository Group creation disabled')), + ('hg.repogroup.create.true', _('Repository Group creation enabled')), + + ('hg.usergroup.create.false', _('User Group creation disabled')), + ('hg.usergroup.create.true', _('User Group creation enabled')), + + ('hg.create.none', _('Repository creation disabled')), + ('hg.create.repository', _('Repository creation enabled')), + + ('hg.fork.none', _('Repository forking disabled')), + ('hg.fork.repository', _('Repository forking enabled')), + + ('hg.register.none', _('Registration disabled')), + ('hg.register.manual_activate', _('User Registration with manual account activation')), + ('hg.register.auto_activate', _('User Registration with automatic account activation')), + + ('hg.extern_activate.manual', _('Manual activation of external account')), + ('hg.extern_activate.auto', _('Automatic activation of external account')), + + ] + + #definition of system default permissions for DEFAULT user + DEFAULT_USER_PERMISSIONS = [ + 'repository.read', + 'group.read', + 'usergroup.read', + 'hg.create.repository', + 'hg.fork.repository', + 'hg.register.manual_activate', + 'hg.extern_activate.auto', + ] + + # defines which permissions are more important higher the more important + # Weight defines which permissions are more important. + # The higher number the more important. + PERM_WEIGHTS = { + 'repository.none': 0, + 'repository.read': 1, + 'repository.write': 3, + 'repository.admin': 4, + + 'group.none': 0, + 'group.read': 1, + 'group.write': 3, + 'group.admin': 4, + + 'usergroup.none': 0, + 'usergroup.read': 1, + 'usergroup.write': 3, + 'usergroup.admin': 4, + 'hg.repogroup.create.false': 0, + 'hg.repogroup.create.true': 1, + + 'hg.usergroup.create.false': 0, + 'hg.usergroup.create.true': 1, + + 'hg.fork.none': 0, + 'hg.fork.repository': 1, + 'hg.create.none': 0, + 'hg.create.repository': 1 + } + + permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, self.permission_id, self.permission_name + ) + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.permission_name == key).scalar() + + @classmethod + def get_default_perms(cls, default_user_id): + q = Session().query(UserRepoToPerm, Repository, cls)\ + .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ + .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_group_perms(cls, default_user_id): + q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\ + .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\ + .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoGroupToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_user_group_perms(cls, default_user_id): + q = Session().query(UserUserGroupToPerm, UserGroup, cls)\ + .join((UserGroup, UserUserGroupToPerm.user_group_id == UserGroup.users_group_id))\ + .join((cls, UserUserGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserUserGroupToPerm.user_id == default_user_id) + + return q.all() + + +class UserRepoToPerm(Base, BaseModel): + __tablename__ = 'repo_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'repository_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + repository = relationship('Repository') + permission = relationship('Permission') + + @classmethod + def create(cls, user, repository, permission): + n = cls() + n.user = user + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.repository) + + +class UserUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'user_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + user_group = relationship('UserGroup') + permission = relationship('Permission') + + @classmethod + def create(cls, user, user_group, permission): + n = cls() + n.user = user + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.user_group) + + +class UserToPerm(Base, BaseModel): + __tablename__ = 'user_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + permission = relationship('Permission', lazy='joined') + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.permission) + + +class UserGroupRepoToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_to_perm' + __table_args__ = ( + UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + repository = relationship('Repository') + + @classmethod + def create(cls, users_group, repository, permission): + n = cls() + n.users_group = users_group + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.users_group, self.repository) + + +class UserGroupUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_group_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'), + CheckConstraint('target_user_group_id != user_group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id') + user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id') + permission = relationship('Permission') + + @classmethod + def create(cls, target_user_group, user_group, permission): + n = cls() + n.target_user_group = target_user_group + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.target_user_group, self.user_group) + + +class UserGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'permission_id',), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + + +class UserRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'user_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + group = relationship('RepoGroup') + permission = relationship('Permission') + + +class UserGroupRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + group = relationship('RepoGroup') + + +class Statistics(Base, BaseModel): + __tablename__ = 'statistics' + __table_args__ = ( + UniqueConstraint('repository_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) + stat_on_revision = Column("stat_on_revision", Integer(), nullable=False) + commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data + commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data + languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data + + repository = relationship('Repository', single_parent=True) + + +class UserFollowing(Base, BaseModel): + __tablename__ = 'user_followings' + __table_args__ = ( + UniqueConstraint('user_id', 'follows_repository_id'), + UniqueConstraint('user_id', 'follows_user_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None) + follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + + user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') + + follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') + follows_repository = relationship('Repository', order_by='Repository.repo_name') + + @classmethod + def get_repo_followers(cls, repo_id): + return cls.query().filter(cls.follows_repo_id == repo_id) + + +class CacheInvalidation(Base, BaseModel): + __tablename__ = 'cache_invalidation' + __table_args__ = ( + UniqueConstraint('cache_key'), + Index('key_idx', 'cache_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + # cache_id, not used + cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + # cache_key as created by _get_cache_key + cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # cache_args is a repo_name + cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # instance sets cache_active True when it is caching, + # other instances set cache_active to False to indicate that this cache is invalid + cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False) + + def __init__(self, cache_key, repo_name=''): + self.cache_key = cache_key + self.cache_args = repo_name + self.cache_active = False + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % (self.__class__.__name__, + self.cache_id, self.cache_key, self.cache_active) + + def _cache_key_partition(self): + prefix, repo_name, suffix = self.cache_key.partition(self.cache_args) + return prefix, repo_name, suffix + + def get_prefix(self): + """ + get prefix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[0] + + def get_suffix(self): + """ + get suffix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[2] + + @classmethod + def clear_cache(cls): + """ + Delete all cache keys from database. + Should only be run when all instances are down and all entries thus stale. + """ + cls.query().delete() + Session().commit() + + @classmethod + def _get_cache_key(cls, key): + """ + Wrapper for generating a unique cache key for this instance and "key". + key must / will start with a repo_name which will be stored in .cache_args . + """ + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') + return "%s%s" % (prefix, key) + + @classmethod + def set_invalidate(cls, repo_name, delete=False): + """ + Mark all caches of a repo as invalid in the database. + """ + inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all() + + try: + for inv_obj in inv_objs: + log.debug('marking %s key for invalidation based on repo_name=%s' + % (inv_obj, safe_str(repo_name))) + if delete: + Session().delete(inv_obj) + else: + inv_obj.cache_active = False + Session().add(inv_obj) + Session().commit() + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + + @classmethod + def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None): + """ + Mark this cache key as active and currently cached. + Return True if the existing cache registration still was valid. + Return False to indicate that it had been invalidated and caches should be refreshed. + """ + + key = (repo_name + '_' + kind) if kind else repo_name + cache_key = cls._get_cache_key(key) + + if valid_cache_keys and cache_key in valid_cache_keys: + return True + + try: + inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar() + if not inv_obj: + inv_obj = CacheInvalidation(cache_key, repo_name) + was_valid = inv_obj.cache_active + inv_obj.cache_active = True + Session().add(inv_obj) + Session().commit() + return was_valid + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + return False + + @classmethod + def get_valid_cache_keys(cls): + """ + Return opaque object with information of which caches still are valid + and can be used without checking for invalidation. + """ + return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all()) + + +class ChangesetComment(Base, BaseModel): + __tablename__ = 'changeset_comments' + __table_args__ = ( + Index('cc_revision_idx', 'revision'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + revision = Column('revision', String(40), nullable=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + line_no = Column('line_no', Unicode(10), nullable=True) + hl_lines = Column('hl_lines', Unicode(512), nullable=True) + f_path = Column('f_path', Unicode(1000), nullable=True) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) + text = Column('text', UnicodeText(25000), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan") + pull_request = relationship('PullRequest', lazy='joined') + + @classmethod + def get_users(cls, revision=None, pull_request_id=None): + """ + Returns user associated with this ChangesetComment. ie those + who actually commented + + :param cls: + :param revision: + """ + q = Session().query(User)\ + .join(ChangesetComment.author) + if revision: + q = q.filter(cls.revision == revision) + elif pull_request_id: + q = q.filter(cls.pull_request_id == pull_request_id) + return q.all() + + +class ChangesetStatus(Base, BaseModel): + __tablename__ = 'changeset_statuses' + __table_args__ = ( + Index('cs_revision_idx', 'revision'), + Index('cs_version_idx', 'version'), + UniqueConstraint('repo_id', 'revision', 'version'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed' + STATUS_APPROVED = 'approved' + STATUS_REJECTED = 'rejected' + STATUS_UNDER_REVIEW = 'under_review' + + STATUSES = [ + (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default + (STATUS_APPROVED, _("Approved")), + (STATUS_REJECTED, _("Rejected")), + (STATUS_UNDER_REVIEW, _("Under Review")), + ] + + changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + revision = Column('revision', String(40), nullable=False) + status = Column('status', String(128), nullable=False, default=DEFAULT) + changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id')) + modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now) + version = Column('version', Integer(), nullable=False, default=0) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + comment = relationship('ChangesetComment', lazy='joined') + pull_request = relationship('PullRequest', lazy='joined') + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, + self.status, self.author + ) + + @classmethod + def get_status_lbl(cls, value): + return dict(cls.STATUSES).get(value) + + @property + def status_lbl(self): + return ChangesetStatus.get_status_lbl(self.status) + + +class PullRequest(Base, BaseModel): + __tablename__ = 'pull_requests' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + # values for .status + STATUS_NEW = u'new' + STATUS_OPEN = u'open' + STATUS_CLOSED = u'closed' + + pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) + title = Column('title', Unicode(256), nullable=True) + description = Column('description', UnicodeText(10240), nullable=True) + status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW) # only for closedness, not approve/reject/etc + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max + org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + org_ref = Column('org_ref', Unicode(256), nullable=False) + other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + other_ref = Column('other_ref', Unicode(256), nullable=False) + + @hybrid_property + def revisions(self): + return self._revisions.split(':') + + @revisions.setter + def revisions(self, val): + self._revisions = ':'.join(val) + + @property + def org_ref_parts(self): + return self.org_ref.split(':') + + @property + def other_ref_parts(self): + return self.other_ref.split(':') + + author = relationship('User', lazy='joined') + reviewers = relationship('PullRequestReviewers', + cascade="all, delete, delete-orphan") + org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') + other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id') + statuses = relationship('ChangesetStatus') + comments = relationship('ChangesetComment', + cascade="all, delete, delete-orphan") + + def is_closed(self): + return self.status == self.STATUS_CLOSED + + @property + def last_review_status(self): + return self.statuses[-1].status if self.statuses else '' + + def __json__(self): + return dict( + revisions=self.revisions + ) + + +class PullRequestReviewers(Base, BaseModel): + __tablename__ = 'pull_request_reviewers' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + def __init__(self, user=None, pull_request=None): + self.user = user + self.pull_request = pull_request + + pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True) + + user = relationship('User') + pull_request = relationship('PullRequest') + + +class Notification(Base, BaseModel): + __tablename__ = 'notifications' + __table_args__ = ( + Index('notification_type_idx', 'type'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + TYPE_CHANGESET_COMMENT = u'cs_comment' + TYPE_MESSAGE = u'message' + TYPE_MENTION = u'mention' + TYPE_REGISTRATION = u'registration' + TYPE_PULL_REQUEST = u'pull_request' + TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' + + notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) + subject = Column('subject', Unicode(512), nullable=True) + body = Column('body', UnicodeText(50000), nullable=True) + created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + type_ = Column('type', Unicode(256)) + + created_by_user = relationship('User') + notifications_to_users = relationship('UserNotification', lazy='joined', + cascade="all, delete, delete-orphan") + + @property + def recipients(self): + return [x.user for x in UserNotification.query()\ + .filter(UserNotification.notification == self)\ + .order_by(UserNotification.user_id.asc()).all()] + + @classmethod + def create(cls, created_by, subject, body, recipients, type_=None): + if type_ is None: + type_ = Notification.TYPE_MESSAGE + + notification = cls() + notification.created_by_user = created_by + notification.subject = subject + notification.body = body + notification.type_ = type_ + notification.created_on = datetime.datetime.now() + + for u in recipients: + assoc = UserNotification() + assoc.notification = notification + u.notifications.append(assoc) + Session().add(notification) + return notification + + @property + def description(self): + from kallithea.model.notification import NotificationModel + return NotificationModel().make_description(self) + + +class UserNotification(Base, BaseModel): + __tablename__ = 'user_to_notification' + __table_args__ = ( + UniqueConstraint('user_id', 'notification_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True) + notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True) + read = Column('read', Boolean, default=False) + sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None) + + user = relationship('User', lazy="joined") + notification = relationship('Notification', lazy="joined", + order_by=lambda: Notification.created_on.desc(),) + + def mark_as_read(self): + self.read = True + Session().add(self) + + +class Gist(Base, BaseModel): + __tablename__ = 'gists' + __table_args__ = ( + Index('g_gist_access_id_idx', 'gist_access_id'), + Index('g_created_on_idx', 'created_on'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + GIST_PUBLIC = u'public' + GIST_PRIVATE = u'private' + + gist_id = Column('gist_id', Integer(), primary_key=True) + gist_access_id = Column('gist_access_id', Unicode(250)) + gist_description = Column('gist_description', UnicodeText(1024)) + gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True) + gist_expires = Column('gist_expires', Float(53), nullable=False) + gist_type = Column('gist_type', Unicode(128), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + owner = relationship('User') + + @classmethod + def get_or_404(cls, id_): + res = cls.query().filter(cls.gist_access_id == id_).scalar() + if not res: + raise HTTPNotFound + return res + + @classmethod + def get_by_access_id(cls, gist_access_id): + return cls.query().filter(cls.gist_access_id == gist_access_id).scalar() + + def gist_url(self): + import kallithea + alias_url = kallithea.CONFIG.get('gist_alias_url') + if alias_url: + return alias_url.replace('{gistid}', self.gist_access_id) + + from pylons import url + return url('gist', gist_id=self.gist_access_id, qualified=True) + + @classmethod + def base_path(cls): + """ + Returns base path when all gists are stored + + :param cls: + """ + from kallithea.model.gist import GIST_STORE_LOC + q = Session().query(Ui)\ + .filter(Ui.ui_key == URL_SEP) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return os.path.join(q.one().ui_value, GIST_STORE_LOC) + + def get_api_data(self): + """ + Common function for generating gist related data for API + """ + gist = self + data = dict( + gist_id=gist.gist_id, + type=gist.gist_type, + access_id=gist.gist_access_id, + description=gist.gist_description, + url=gist.gist_url(), + expires=gist.gist_expires, + created_on=gist.created_on, + ) + return data + + def __json__(self): + data = dict( + ) + data.update(self.get_api_data()) + return data + ## SCM functions + + @property + def scm_instance(self): + from kallithea.lib.vcs import get_repo + base_path = self.base_path() + return get_repo(os.path.join(*map(safe_str, + [base_path, self.gist_access_id]))) + + +class DbMigrateVersion(Base, BaseModel): + __tablename__ = 'db_migrate_version' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + repository_id = Column('repository_id', String(250), primary_key=True) + repository_path = Column('repository_path', Text) + version = Column('version', Integer) diff --git a/kallithea/lib/dbmigrate/schema/db_2_0_1.py b/kallithea/lib/dbmigrate/schema/db_2_0_1.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/schema/db_2_0_1.py @@ -0,0 +1,2335 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.db +~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import os +import time +import logging +import datetime +import traceback +import hashlib +import collections +import functools + +from sqlalchemy import * +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import relationship, joinedload, class_mapper, validates +from sqlalchemy.exc import DatabaseError +from beaker.cache import cache_region, region_invalidate +from webob.exc import HTTPNotFound + +from pylons.i18n.translation import lazy_ugettext as _ + +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset + +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ + safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache + +from kallithea.model.meta import Base, Session + +from kallithea import DB_PREFIX + +URL_SEP = '/' +log = logging.getLogger(__name__) + +#============================================================================== +# BASE CLASSES +#============================================================================== + +_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest() + + +class BaseModel(object): + """ + Base Model for all classess + """ + + @classmethod + def _get_keys(cls): + """return column names for this model """ + return class_mapper(cls).c.keys() + + def get_dict(self): + """ + return dict with keys and values corresponding + to this model data """ + + d = {} + for k in self._get_keys(): + d[k] = getattr(self, k) + + # also use __json__() if present to get additional fields + _json_attr = getattr(self, '__json__', None) + if _json_attr: + # update with attributes from __json__ + if callable(_json_attr): + _json_attr = _json_attr() + for k, val in _json_attr.iteritems(): + d[k] = val + return d + + def get_appstruct(self): + """return list with keys and values tupples corresponding + to this model data """ + + l = [] + for k in self._get_keys(): + l.append((k, getattr(self, k),)) + return l + + def populate_obj(self, populate_dict): + """populate model with data from given populate_dict""" + + for k in self._get_keys(): + if k in populate_dict: + setattr(self, k, populate_dict[k]) + + @classmethod + def query(cls): + return Session().query(cls) + + @classmethod + def get(cls, id_): + if id_: + return cls.query().get(id_) + + @classmethod + def get_or_404(cls, id_): + try: + id_ = int(id_) + except (TypeError, ValueError): + raise HTTPNotFound + + res = cls.query().get(id_) + if not res: + raise HTTPNotFound + return res + + @classmethod + def getAll(cls): + # deprecated and left for backward compatibility + return cls.get_all() + + @classmethod + def get_all(cls): + return cls.query().all() + + @classmethod + def delete(cls, id_): + obj = cls.query().get(id_) + Session().delete(obj) + + def __repr__(self): + if hasattr(self, '__unicode__'): + # python repr needs to return str + try: + return safe_str(self.__unicode__()) + except UnicodeDecodeError: + pass + return '' % (self.__class__.__name__) + + +class Setting(Base, BaseModel): + SETTINGS_TYPES = { + 'str': safe_str, + 'int': safe_int, + 'unicode': safe_unicode, + 'bool': str2bool, + 'list': functools.partial(aslist, sep=',') + } + __tablename__ = DB_PREFIX + 'settings' + __table_args__ = ( + UniqueConstraint('app_settings_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + app_settings_name = Column("app_settings_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_value = Column("app_settings_value", String(4096, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_type = Column("app_settings_type", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __init__(self, key='', val='', type='unicode'): + self.app_settings_name = key + self.app_settings_value = val + self.app_settings_type = type + + @validates('_app_settings_value') + def validate_settings_value(self, key, val): + assert type(val) == unicode + return val + + @hybrid_property + def app_settings_value(self): + v = self._app_settings_value + _type = self.app_settings_type + converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode'] + return converter(v) + + @app_settings_value.setter + def app_settings_value(self, val): + """ + Setter that will always make sure we use unicode in app_settings_value + + :param val: + """ + self._app_settings_value = safe_unicode(val) + + @hybrid_property + def app_settings_type(self): + return self._app_settings_type + + @app_settings_type.setter + def app_settings_type(self, val): + if val not in self.SETTINGS_TYPES: + raise Exception('type must be one of %s got %s' + % (self.SETTINGS_TYPES.keys(), val)) + self._app_settings_type = val + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % ( + self.__class__.__name__, + self.app_settings_name, self.app_settings_value, self.app_settings_type + ) + + @classmethod + def get_by_name(cls, key): + return cls.query()\ + .filter(cls.app_settings_name == key).scalar() + + @classmethod + def get_by_name_or_create(cls, key, val='', type='unicode'): + res = cls.get_by_name(key) + if not res: + res = cls(key, val, type) + return res + + @classmethod + def create_or_update(cls, key, val=Optional(''), type=Optional('unicode')): + """ + Creates or updates Kallithea setting. If updates is triggered it will only + update parameters that are explicityl set Optional instance will be skipped + + :param key: + :param val: + :param type: + :return: + """ + res = cls.get_by_name(key) + if not res: + val = Optional.extract(val) + type = Optional.extract(type) + res = cls(key, val, type) + else: + res.app_settings_name = key + if not isinstance(val, Optional): + # update if set + res.app_settings_value = val + if not isinstance(type, Optional): + # update if set + res.app_settings_type = type + return res + + @classmethod + def get_app_settings(cls, cache=False): + + ret = cls.query() + + if cache: + ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) + + if not ret: + raise Exception('Could not get application settings !') + settings = {} + for each in ret: + settings[each.app_settings_name] = \ + each.app_settings_value + + return settings + + @classmethod + def get_auth_plugins(cls, cache=False): + auth_plugins = cls.get_by_name("auth_plugins").app_settings_value + return auth_plugins + + @classmethod + def get_auth_settings(cls, cache=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('auth_')).all() + fd = {} + for row in ret: + fd.update({row.app_settings_name: row.app_settings_value}) + + return fd + + @classmethod + def get_default_repo_settings(cls, cache=False, strip_prefix=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('default_')).all() + fd = {} + for row in ret: + key = row.app_settings_name + if strip_prefix: + key = remove_prefix(key, prefix='default_') + fd.update({key: row.app_settings_value}) + + return fd + + @classmethod + def get_server_info(cls): + import pkg_resources + import platform + import kallithea + from kallithea.lib.utils import check_git_version + mods = [(p.project_name, p.version) for p in pkg_resources.working_set] + info = { + 'modules': sorted(mods, key=lambda k: k[0].lower()), + 'py_version': platform.python_version(), + 'platform': safe_unicode(platform.platform()), + 'kallithea_version': kallithea.__version__, + 'git_version': safe_unicode(check_git_version()), + 'git_path': kallithea.CONFIG.get('git_path') + } + return info + + +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' + __table_args__ = ( + UniqueConstraint('ui_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + HOOK_UPDATE = 'changegroup.update' + HOOK_REPO_SIZE = 'changegroup.repo_size' + HOOK_PUSH = 'changegroup.push_logger' + HOOK_PRE_PUSH = 'prechangegroup.pre_push' + HOOK_PULL = 'outgoing.pull_logger' + HOOK_PRE_PULL = 'preoutgoing.pre_pull' + + ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) + + # def __init__(self, section='', key='', value=''): + # self.ui_section = section + # self.ui_key = key + # self.ui_value = value + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.ui_key == key).scalar() + + @classmethod + def get_builtin_hooks(cls): + q = cls.query() + q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + return q.all() + + @classmethod + def get_custom_hooks(cls): + q = cls.query() + q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + q = q.filter(cls.ui_section == 'hooks') + return q.all() + + @classmethod + def get_repos_location(cls): + return cls.get_by_key('/').ui_value + + @classmethod + def create_or_update_hook(cls, key, val): + new_ui = cls.get_by_key(key) or cls() + new_ui.ui_section = 'hooks' + new_ui.ui_active = True + new_ui.ui_key = key + new_ui.ui_value = val + + Session().add(new_ui) + + def __repr__(self): + return '' % (self.__class__.__name__, self.ui_key, + self.ui_value) + + +class User(Base, BaseModel): + __tablename__ = 'users' + __table_args__ = ( + UniqueConstraint('username'), UniqueConstraint('email'), + Index('u_username_idx', 'username'), + Index('u_email_idx', 'email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + DEFAULT_USER = 'default' + + user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + admin = Column("admin", Boolean(), nullable=True, unique=None, default=False) + name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) + extern_type = Column("extern_type", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + extern_name = Column("extern_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + user_log = relationship('UserLog') + user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') + + repositories = relationship('Repository') + user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all') + followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all') + + repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all') + repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all') + + group_member = relationship('UserGroupMember', cascade='all') + + notifications = relationship('UserNotification', cascade='all') + # notifications assigned to this user + user_created_notifications = relationship('Notification', cascade='all') + # comments created by this user + user_comments = relationship('ChangesetComment', cascade='all') + #extra emails for this user + user_emails = relationship('UserEmailMap', cascade='all') + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + @property + def firstname(self): + # alias for future + return self.name + + @property + def emails(self): + other = UserEmailMap.query().filter(UserEmailMap.user==self).all() + return [self.email] + [x.email for x in other] + + @property + def ip_addresses(self): + ret = UserIpMap.query().filter(UserIpMap.user == self).all() + return [x.ip_addr for x in ret] + + @property + def username_and_name(self): + return '%s (%s %s)' % (self.username, self.firstname, self.lastname) + + @property + def full_name(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def full_name_or_username(self): + return ('%s %s' % (self.firstname, self.lastname) + if (self.firstname and self.lastname) else self.username) + + @property + def full_contact(self): + return '%s %s <%s>' % (self.firstname, self.lastname, self.email) + + @property + def short_contact(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def is_admin(self): + return self.admin + + @property + def AuthUser(self): + """ + Returns instance of AuthUser for this user + """ + from kallithea.lib.auth import AuthUser + return AuthUser(user_id=self.user_id, api_key=self.api_key, + username=self.username) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.user_id, self.username) + + @classmethod + def get_by_username(cls, username, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.username.ilike(username)) + else: + q = cls.query().filter(cls.username == username) + + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(username) + ) + ) + return q.scalar() + + @classmethod + def get_by_api_key(cls, api_key, cache=False): + q = cls.query().filter(cls.api_key == api_key) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_api_key_%s" % api_key)) + return q.scalar() + + @classmethod + def get_by_email(cls, email, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.email.ilike(email)) + else: + q = cls.query().filter(cls.email == email) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_key_%s" % email)) + + ret = q.scalar() + if ret is None: + q = UserEmailMap.query() + # try fetching in alternate email map + if case_insensitive: + q = q.filter(UserEmailMap.email.ilike(email)) + else: + q = q.filter(UserEmailMap.email == email) + q = q.options(joinedload(UserEmailMap.user)) + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_map_key_%s" % email)) + ret = getattr(q.scalar(), 'user', None) + + return ret + + @classmethod + def get_from_cs_author(cls, author): + """ + Tries to get User objects out of commit author string + + :param author: + """ + from kallithea.lib.helpers import email, author_name + # Valid email in the attribute passed, see if they're in the system + _email = email(author) + if _email: + user = cls.get_by_email(_email, case_insensitive=True) + if user: + return user + # Maybe we can match by username? + _author = author_name(author) + user = cls.get_by_username(_author, case_insensitive=True) + if user: + return user + + def update_lastlogin(self): + """Update user lastlogin""" + self.last_login = datetime.datetime.now() + Session().add(self) + log.debug('updated user %s lastlogin' % self.username) + + @classmethod + def get_first_admin(cls): + user = User.query().filter(User.admin == True).first() + if user is None: + raise Exception('Missing administrative account!') + return user + + @classmethod + def get_default_user(cls, cache=False): + user = User.get_by_username(User.DEFAULT_USER, cache=cache) + if user is None: + raise Exception('Missing default account!') + return user + + def get_api_data(self): + """ + Common function for generating user related data for API + """ + user = self + data = dict( + user_id=user.user_id, + username=user.username, + firstname=user.name, + lastname=user.lastname, + email=user.email, + emails=user.emails, + api_key=user.api_key, + active=user.active, + admin=user.admin, + extern_type=user.extern_type, + extern_name=user.extern_name, + last_login=user.last_login, + ip_addresses=user.ip_addresses + ) + return data + + def __json__(self): + data = dict( + full_name=self.full_name, + full_name_or_username=self.full_name_or_username, + short_contact=self.short_contact, + full_contact=self.full_contact + ) + data.update(self.get_api_data()) + return data + + +class UserEmailMap(Base, BaseModel): + __tablename__ = 'user_email_map' + __table_args__ = ( + Index('uem_email_idx', 'email'), + UniqueConstraint('email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + user = relationship('User', lazy='joined') + + @validates('_email') + def validate_email(self, key, email): + # check if this email is not main one + main_email = Session().query(User).filter(User.email == email).scalar() + if main_email is not None: + raise AttributeError('email %s is present is user table' % email) + return email + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + +class UserIpMap(Base, BaseModel): + __tablename__ = 'user_ip_map' + __table_args__ = ( + UniqueConstraint('user_id', 'ip_addr'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + user = relationship('User', lazy='joined') + + @classmethod + def _get_ip_range(cls, ip_addr): + from kallithea.lib import ipaddr + net = ipaddr.IPNetwork(address=ip_addr) + return [str(net.network), str(net.broadcast)] + + def __json__(self): + return dict( + ip_addr=self.ip_addr, + ip_range=self._get_ip_range(self.ip_addr) + ) + + +class UserLog(Base, BaseModel): + __tablename__ = 'user_logs' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True) + repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.repository_name, + self.action) + + @property + def action_as_day(self): + return datetime.date(*self.action_date.timetuple()[:3]) + + user = relationship('User') + repository = relationship('Repository', cascade='') + + +class UserGroup(Base, BaseModel): + __tablename__ = 'users_groups' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + user_group_description = Column("user_group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined") + users_group_to_perm = relationship('UserGroupToPerm', cascade='all') + users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all') + user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all') + + user = relationship('User') + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.users_group_id, + self.users_group_name) + + @classmethod + def get_by_group_name(cls, group_name, cache=False, + case_insensitive=False): + if case_insensitive: + q = cls.query().filter(cls.users_group_name.ilike(group_name)) + else: + q = cls.query().filter(cls.users_group_name == group_name) + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(group_name) + ) + ) + return q.scalar() + + @classmethod + def get(cls, user_group_id, cache=False): + user_group = cls.query() + if cache: + user_group = user_group.options(FromCache("sql_cache_short", + "get_users_group_%s" % user_group_id)) + return user_group.get(user_group_id) + + def get_api_data(self, with_members=True): + user_group = self + + data = dict( + users_group_id=user_group.users_group_id, + group_name=user_group.users_group_name, + group_description=user_group.user_group_description, + active=user_group.users_group_active, + owner=user_group.user.username, + ) + if with_members: + members = [] + for user in user_group.members: + user = user.user + members.append(user.get_api_data()) + data['members'] = members + + return data + + +class UserGroupMember(Base, BaseModel): + __tablename__ = 'users_groups_members' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + + user = relationship('User', lazy='joined') + users_group = relationship('UserGroup') + + def __init__(self, gr_id='', u_id=''): + self.users_group_id = gr_id + self.user_id = u_id + + +class RepositoryField(Base, BaseModel): + __tablename__ = 'repositories_fields' + __table_args__ = ( + UniqueConstraint('repository_id', 'field_key'), # no-multi field + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields + + repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + field_key = Column("field_key", String(250, convert_unicode=False, assert_unicode=None)) + field_label = Column("field_label", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_value = Column("field_value", String(10000, convert_unicode=False, assert_unicode=None), nullable=False) + field_desc = Column("field_desc", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_type = Column("field_type", String(256), nullable=False, unique=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repository = relationship('Repository') + + @property + def field_key_prefixed(self): + return 'ex_%s' % self.field_key + + @classmethod + def un_prefix_key(cls, key): + if key.startswith(cls.PREFIX): + return key[len(cls.PREFIX):] + return key + + @classmethod + def get_by_key_name(cls, key, repo): + row = cls.query()\ + .filter(cls.repository == repo)\ + .filter(cls.field_key == key).scalar() + return row + + +class Repository(Base, BaseModel): + __tablename__ = 'repositories' + __table_args__ = ( + UniqueConstraint('repo_name'), + Index('r_repo_name_idx', 'repo_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + private = Column("private", Boolean(), nullable=True, unique=None, default=None) + enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True) + enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True) + description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data + + fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) + + user = relationship('User') + fork = relationship('Repository', remote_side=repo_id) + group = relationship('RepoGroup') + repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + stats = relationship('Statistics', cascade='all', uselist=False) + + followers = relationship('UserFollowing', + primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', + cascade='all') + extra_fields = relationship('RepositoryField', + cascade="all, delete, delete-orphan") + + logs = relationship('UserLog') + comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan") + + pull_requests_org = relationship('PullRequest', + primaryjoin='PullRequest.org_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + pull_requests_other = relationship('PullRequest', + primaryjoin='PullRequest.other_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, + safe_unicode(self.repo_name)) + + @hybrid_property + def locked(self): + # always should return [user_id, timelocked] + if self._locked: + _lock_info = self._locked.split(':') + return int(_lock_info[0]), _lock_info[1] + return [None, None] + + @locked.setter + def locked(self, val): + if val and isinstance(val, (list, tuple)): + self._locked = ':'.join(map(str, val)) + else: + self._locked = None + + @hybrid_property + def changeset_cache(self): + from kallithea.lib.vcs.backends.base import EmptyChangeset + dummy = EmptyChangeset().__json__() + if not self._changeset_cache: + return dummy + try: + return json.loads(self._changeset_cache) + except TypeError: + return dummy + + @changeset_cache.setter + def changeset_cache(self, val): + try: + self._changeset_cache = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def normalize_repo_name(cls, repo_name): + """ + Normalizes os specific repo_name to the format internally stored inside + dabatabase using URL_SEP + + :param cls: + :param repo_name: + """ + return cls.url_sep().join(repo_name.split(os.sep)) + + @classmethod + def get_by_repo_name(cls, repo_name): + q = Session().query(cls).filter(cls.repo_name == repo_name) + q = q.options(joinedload(Repository.fork))\ + .options(joinedload(Repository.user))\ + .options(joinedload(Repository.group)) + return q.scalar() + + @classmethod + def get_by_full_path(cls, repo_full_path): + repo_name = repo_full_path.split(cls.base_path(), 1)[-1] + repo_name = cls.normalize_repo_name(repo_name) + return cls.get_by_repo_name(repo_name.strip(URL_SEP)) + + @classmethod + def get_repo_forks(cls, repo_id): + return cls.query().filter(Repository.fork_id == repo_id) + + @classmethod + def base_path(cls): + """ + Returns base path when all repos are stored + + :param cls: + """ + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def forks(self): + """ + Return forks of this repo + """ + return Repository.get_repo_forks(self.repo_id) + + @property + def parent(self): + """ + Returns fork parent + """ + return self.fork + + @property + def just_name(self): + return self.repo_name.split(Repository.url_sep())[-1] + + @property + def groups_with_parents(self): + groups = [] + if self.group is None: + return groups + + cur_gr = self.group + groups.insert(0, cur_gr) + while 1: + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + groups.insert(0, gr) + + return groups + + @property + def groups_and_repo(self): + return self.groups_with_parents, self.just_name, self.repo_name + + @LazyProperty + def repo_path(self): + """ + Returns base full path for that repository means where it actually + exists on a filesystem + """ + q = Session().query(Ui).filter(Ui.ui_key == + Repository.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def repo_full_path(self): + p = [self.repo_path] + # we need to split the name by / since this is how we store the + # names in the database, but that eventually needs to be converted + # into a valid system path + p += self.repo_name.split(Repository.url_sep()) + return os.path.join(*map(safe_unicode, p)) + + @property + def cache_keys(self): + """ + Returns associated cache keys for that repo + """ + return CacheInvalidation.query()\ + .filter(CacheInvalidation.cache_args == self.repo_name)\ + .order_by(CacheInvalidation.cache_key)\ + .all() + + def get_new_name(self, repo_name): + """ + returns new full repository name based on assigned group and new new + + :param group_name: + """ + path_prefix = self.group.full_path_splitted if self.group else [] + return Repository.url_sep().join(path_prefix + [repo_name]) + + @property + def _ui(self): + """ + Creates an db based ui object for this repository + """ + from kallithea.lib.utils import make_ui + return make_ui('db', clear_session=False) + + @classmethod + def is_valid(cls, repo_name): + """ + returns True if given repo name is a valid filesystem repository + + :param cls: + :param repo_name: + """ + from kallithea.lib.utils import is_valid_repo + + return is_valid_repo(repo_name, cls.base_path()) + + def get_api_data(self): + """ + Common function for generating repo api data + + """ + repo = self + data = dict( + repo_id=repo.repo_id, + repo_name=repo.repo_name, + repo_type=repo.repo_type, + clone_uri=repo.clone_uri, + private=repo.private, + created_on=repo.created_on, + description=repo.description, + landing_rev=repo.landing_rev, + owner=repo.user.username, + fork_of=repo.fork.repo_name if repo.fork else None, + enable_statistics=repo.enable_statistics, + enable_locking=repo.enable_locking, + enable_downloads=repo.enable_downloads, + last_changeset=repo.changeset_cache, + locked_by=User.get(self.locked[0]).get_api_data() \ + if self.locked[0] else None, + locked_date=time_to_datetime(self.locked[1]) \ + if self.locked[1] else None + ) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) + if repository_fields: + for f in self.extra_fields: + data[f.field_key_prefixed] = f.field_value + + return data + + @classmethod + def lock(cls, repo, user_id, lock_time=None): + if not lock_time: + lock_time = time.time() + repo.locked = [user_id, lock_time] + Session().add(repo) + Session().commit() + + @classmethod + def unlock(cls, repo): + repo.locked = None + Session().add(repo) + Session().commit() + + @classmethod + def getlock(cls, repo): + return repo.locked + + @property + def last_db_change(self): + return self.updated_on + + def clone_url(self, **override): + from pylons import url + from urlparse import urlparse + import urllib + parsed_url = urlparse(url('home', qualified=True)) + default_clone_uri = '%(scheme)s://%(user)s%(pass)s%(netloc)s%(prefix)s%(path)s' + decoded_path = safe_unicode(urllib.unquote(parsed_url.path)) + args = { + 'user': '', + 'pass': '', + 'scheme': parsed_url.scheme, + 'netloc': parsed_url.netloc, + 'prefix': decoded_path, + 'path': self.repo_name + } + + args.update(override) + return default_clone_uri % args + + #========================================================================== + # SCM PROPERTIES + #========================================================================== + + def get_changeset(self, rev=None): + return get_changeset_safe(self.scm_instance, rev) + + def get_landing_changeset(self): + """ + Returns landing changeset, or if that doesn't exist returns the tip + """ + cs = self.get_changeset(self.landing_rev) or self.get_changeset() + return cs + + def update_changeset_cache(self, cs_cache=None): + """ + Update cache of last changeset for repository, keys should be:: + + short_id + raw_id + revision + message + date + author + + :param cs_cache: + """ + from kallithea.lib.vcs.backends.base import BaseChangeset + if cs_cache is None: + cs_cache = EmptyChangeset() + # use no-cache version here + scm_repo = self.scm_instance_no_cache() + if scm_repo: + cs_cache = scm_repo.get_changeset() + + if isinstance(cs_cache, BaseChangeset): + cs_cache = cs_cache.__json__() + + if (cs_cache != self.changeset_cache or not self.changeset_cache): + _default = datetime.datetime.fromtimestamp(0) + last_change = cs_cache.get('date') or _default + log.debug('updated repo %s with new cs cache %s' + % (self.repo_name, cs_cache)) + self.updated_on = last_change + self.changeset_cache = cs_cache + Session().add(self) + Session().commit() + else: + log.debug('Skipping repo:%s already with latest changes' + % self.repo_name) + + @property + def tip(self): + return self.get_changeset('tip') + + @property + def author(self): + return self.tip.author + + @property + def last_change(self): + return self.scm_instance.last_change + + def get_comments(self, revisions=None): + """ + Returns comments for this repository grouped by revisions + + :param revisions: filter query by revisions only + """ + cmts = ChangesetComment.query()\ + .filter(ChangesetComment.repo == self) + if revisions: + cmts = cmts.filter(ChangesetComment.revision.in_(revisions)) + grouped = collections.defaultdict(list) + for cmt in cmts.all(): + grouped[cmt.revision].append(cmt) + return grouped + + def statuses(self, revisions=None): + """ + Returns statuses for this repository + + :param revisions: list of revisions to get statuses for + """ + + statuses = ChangesetStatus.query()\ + .filter(ChangesetStatus.repo == self)\ + .filter(ChangesetStatus.version == 0) + if revisions: + statuses = statuses.filter(ChangesetStatus.revision.in_(revisions)) + grouped = {} + + #maybe we have open new pullrequest without a status ? + stat = ChangesetStatus.STATUS_UNDER_REVIEW + status_lbl = ChangesetStatus.get_status_lbl(stat) + for pr in PullRequest.query().filter(PullRequest.org_repo == self).all(): + for rev in pr.revisions: + pr_id = pr.pull_request_id + pr_repo = pr.other_repo.repo_name + grouped[rev] = [stat, status_lbl, pr_id, pr_repo] + + for stat in statuses.all(): + pr_id = pr_repo = None + if stat.pull_request: + pr_id = stat.pull_request.pull_request_id + pr_repo = stat.pull_request.other_repo.repo_name + grouped[stat.revision] = [str(stat.status), stat.status_lbl, + pr_id, pr_repo] + return grouped + + def _repo_size(self): + from kallithea.lib import helpers as h + log.debug('calculating repository size...') + return h.format_byte_size(self.scm_instance.size) + + #========================================================================== + # SCM CACHE INSTANCE + #========================================================================== + + def set_invalidate(self): + """ + Mark caches of this repo as invalid. + """ + CacheInvalidation.set_invalidate(self.repo_name) + + def scm_instance_no_cache(self): + return self.__get_instance() + + @property + def scm_instance(self): + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) + if full_cache: + return self.scm_instance_cached() + return self.__get_instance() + + def scm_instance_cached(self, valid_cache_keys=None): + @cache_region('long_term') + def _c(repo_name): + return self.__get_instance() + rn = self.repo_name + + valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys) + if not valid: + log.debug('Cache for %s invalidated, getting new object' % (rn)) + region_invalidate(_c, None, rn) + else: + log.debug('Getting obj for %s from cache' % (rn)) + return _c(rn) + + def __get_instance(self): + repo_full_path = self.repo_full_path + try: + alias = get_scm(repo_full_path)[0] + log.debug('Creating instance of %s repository from %s' + % (alias, repo_full_path)) + backend = get_backend(alias) + except VCSError: + log.error(traceback.format_exc()) + log.error('Perhaps this repository is in db and not in ' + 'filesystem run rescan repositories with ' + '"destroy old data " option from admin panel') + return + + if alias == 'hg': + + repo = backend(safe_str(repo_full_path), create=False, + baseui=self._ui) + # skip hidden web repository + if repo._get_hidden(): + return + else: + repo = backend(repo_full_path, create=False) + + return repo + + +class RepoGroup(Base, BaseModel): + __tablename__ = 'groups' + __table_args__ = ( + UniqueConstraint('group_name', 'group_parent_id'), + CheckConstraint('group_id != group_parent_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + __mapper_args__ = {'order_by': 'group_name'} + + group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + group_name = Column("group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) + group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + #TODO: create this field in migrations + #created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + parent_group = relationship('RepoGroup', remote_side=group_id) + user = relationship('User') + + def __init__(self, group_name='', parent_group=None): + self.group_name = group_name + self.parent_group = parent_group + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id, + self.group_name) + + @classmethod + def groups_choices(cls, groups=None, show_empty_group=True): + from webhelpers.html import literal as _literal + if not groups: + groups = cls.query().all() + + repo_groups = [] + if show_empty_group: + repo_groups = [('-1', u'-- %s --' % _('top level'))] + sep = ' » ' + _name = lambda k: _literal(sep.join(k)) + + repo_groups.extend([(x.group_id, _name(x.full_path_splitted)) + for x in groups]) + + repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0]) + return repo_groups + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): + if case_insensitive: + gr = cls.query()\ + .filter(cls.group_name.ilike(group_name)) + else: + gr = cls.query()\ + .filter(cls.group_name == group_name) + if cache: + gr = gr.options(FromCache( + "sql_cache_short", + "get_group_%s" % _hash_key(group_name) + ) + ) + return gr.scalar() + + @property + def parents(self): + parents_recursion_limit = 5 + groups = [] + if self.parent_group is None: + return groups + cur_gr = self.parent_group + groups.insert(0, cur_gr) + cnt = 0 + while 1: + cnt += 1 + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + if cnt == parents_recursion_limit: + # this will prevent accidental infinit loops + log.error('group nested more than %s' % + parents_recursion_limit) + break + + groups.insert(0, gr) + return groups + + @property + def children(self): + return RepoGroup.query().filter(RepoGroup.parent_group == self) + + @property + def name(self): + return self.group_name.split(RepoGroup.url_sep())[-1] + + @property + def full_path(self): + return self.group_name + + @property + def full_path_splitted(self): + return self.group_name.split(RepoGroup.url_sep()) + + @property + def repositories(self): + return Repository.query()\ + .filter(Repository.group == self)\ + .order_by(Repository.repo_name) + + @property + def repositories_recursive_count(self): + cnt = self.repositories.count() + + def children_count(group): + cnt = 0 + for child in group.children: + cnt += child.repositories.count() + cnt += children_count(child) + return cnt + + return cnt + children_count(self) + + def _recursive_objects(self, include_repos=True): + all_ = [] + + def _get_members(root_gr): + if include_repos: + for r in root_gr.repositories: + all_.append(r) + childs = root_gr.children.all() + if childs: + for gr in childs: + all_.append(gr) + _get_members(gr) + + _get_members(self) + return [self] + all_ + + def recursive_groups_and_repos(self): + """ + Recursive return all groups, with repositories in those groups + """ + return self._recursive_objects() + + def recursive_groups(self): + """ + Returns all children groups for this group including children of children + """ + return self._recursive_objects(include_repos=False) + + def get_new_name(self, group_name): + """ + returns new full group name based on parent and new name + + :param group_name: + """ + path_prefix = (self.parent_group.full_path_splitted if + self.parent_group else []) + return RepoGroup.url_sep().join(path_prefix + [group_name]) + + def get_api_data(self): + """ + Common function for generating api data + + """ + group = self + data = dict( + group_id=group.group_id, + group_name=group.group_name, + group_description=group.group_description, + parent_group=group.parent_group.group_name if group.parent_group else None, + repositories=[x.repo_name for x in group.repositories], + owner=group.user.username + ) + return data + + +class Permission(Base, BaseModel): + __tablename__ = 'permissions' + __table_args__ = ( + Index('p_perm_name_idx', 'permission_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PERMS = [ + ('hg.admin', _('Kallithea Administrator')), + + ('repository.none', _('Repository no access')), + ('repository.read', _('Repository read access')), + ('repository.write', _('Repository write access')), + ('repository.admin', _('Repository admin access')), + + ('group.none', _('Repository group no access')), + ('group.read', _('Repository group read access')), + ('group.write', _('Repository group write access')), + ('group.admin', _('Repository group admin access')), + + ('usergroup.none', _('User group no access')), + ('usergroup.read', _('User group read access')), + ('usergroup.write', _('User group write access')), + ('usergroup.admin', _('User group admin access')), + + ('hg.repogroup.create.false', _('Repository Group creation disabled')), + ('hg.repogroup.create.true', _('Repository Group creation enabled')), + + ('hg.usergroup.create.false', _('User Group creation disabled')), + ('hg.usergroup.create.true', _('User Group creation enabled')), + + ('hg.create.none', _('Repository creation disabled')), + ('hg.create.repository', _('Repository creation enabled')), + + ('hg.fork.none', _('Repository forking disabled')), + ('hg.fork.repository', _('Repository forking enabled')), + + ('hg.register.none', _('Registration disabled')), + ('hg.register.manual_activate', _('User Registration with manual account activation')), + ('hg.register.auto_activate', _('User Registration with automatic account activation')), + + ('hg.extern_activate.manual', _('Manual activation of external account')), + ('hg.extern_activate.auto', _('Automatic activation of external account')), + + ] + + #definition of system default permissions for DEFAULT user + DEFAULT_USER_PERMISSIONS = [ + 'repository.read', + 'group.read', + 'usergroup.read', + 'hg.create.repository', + 'hg.fork.repository', + 'hg.register.manual_activate', + 'hg.extern_activate.auto', + ] + + # defines which permissions are more important higher the more important + # Weight defines which permissions are more important. + # The higher number the more important. + PERM_WEIGHTS = { + 'repository.none': 0, + 'repository.read': 1, + 'repository.write': 3, + 'repository.admin': 4, + + 'group.none': 0, + 'group.read': 1, + 'group.write': 3, + 'group.admin': 4, + + 'usergroup.none': 0, + 'usergroup.read': 1, + 'usergroup.write': 3, + 'usergroup.admin': 4, + 'hg.repogroup.create.false': 0, + 'hg.repogroup.create.true': 1, + + 'hg.usergroup.create.false': 0, + 'hg.usergroup.create.true': 1, + + 'hg.fork.none': 0, + 'hg.fork.repository': 1, + 'hg.create.none': 0, + 'hg.create.repository': 1 + } + + permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, self.permission_id, self.permission_name + ) + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.permission_name == key).scalar() + + @classmethod + def get_default_perms(cls, default_user_id): + q = Session().query(UserRepoToPerm, Repository, cls)\ + .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ + .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_group_perms(cls, default_user_id): + q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\ + .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\ + .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoGroupToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_user_group_perms(cls, default_user_id): + q = Session().query(UserUserGroupToPerm, UserGroup, cls)\ + .join((UserGroup, UserUserGroupToPerm.user_group_id == UserGroup.users_group_id))\ + .join((cls, UserUserGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserUserGroupToPerm.user_id == default_user_id) + + return q.all() + + +class UserRepoToPerm(Base, BaseModel): + __tablename__ = 'repo_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'repository_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + repository = relationship('Repository') + permission = relationship('Permission') + + @classmethod + def create(cls, user, repository, permission): + n = cls() + n.user = user + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.repository) + + +class UserUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'user_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + user_group = relationship('UserGroup') + permission = relationship('Permission') + + @classmethod + def create(cls, user, user_group, permission): + n = cls() + n.user = user + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.user_group) + + +class UserToPerm(Base, BaseModel): + __tablename__ = 'user_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + permission = relationship('Permission', lazy='joined') + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.permission) + + +class UserGroupRepoToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_to_perm' + __table_args__ = ( + UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + repository = relationship('Repository') + + @classmethod + def create(cls, users_group, repository, permission): + n = cls() + n.users_group = users_group + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.users_group, self.repository) + + +class UserGroupUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_group_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'), + CheckConstraint('target_user_group_id != user_group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id') + user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id') + permission = relationship('Permission') + + @classmethod + def create(cls, target_user_group, user_group, permission): + n = cls() + n.target_user_group = target_user_group + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.target_user_group, self.user_group) + + +class UserGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'permission_id',), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + + +class UserRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'user_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + group = relationship('RepoGroup') + permission = relationship('Permission') + + +class UserGroupRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + group = relationship('RepoGroup') + + +class Statistics(Base, BaseModel): + __tablename__ = 'statistics' + __table_args__ = ( + UniqueConstraint('repository_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) + stat_on_revision = Column("stat_on_revision", Integer(), nullable=False) + commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data + commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data + languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data + + repository = relationship('Repository', single_parent=True) + + +class UserFollowing(Base, BaseModel): + __tablename__ = 'user_followings' + __table_args__ = ( + UniqueConstraint('user_id', 'follows_repository_id'), + UniqueConstraint('user_id', 'follows_user_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None) + follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + + user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') + + follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') + follows_repository = relationship('Repository', order_by='Repository.repo_name') + + @classmethod + def get_repo_followers(cls, repo_id): + return cls.query().filter(cls.follows_repo_id == repo_id) + + +class CacheInvalidation(Base, BaseModel): + __tablename__ = 'cache_invalidation' + __table_args__ = ( + UniqueConstraint('cache_key'), + Index('key_idx', 'cache_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + # cache_id, not used + cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + # cache_key as created by _get_cache_key + cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # cache_args is a repo_name + cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # instance sets cache_active True when it is caching, + # other instances set cache_active to False to indicate that this cache is invalid + cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False) + + def __init__(self, cache_key, repo_name=''): + self.cache_key = cache_key + self.cache_args = repo_name + self.cache_active = False + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % (self.__class__.__name__, + self.cache_id, self.cache_key, self.cache_active) + + def _cache_key_partition(self): + prefix, repo_name, suffix = self.cache_key.partition(self.cache_args) + return prefix, repo_name, suffix + + def get_prefix(self): + """ + get prefix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[0] + + def get_suffix(self): + """ + get suffix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[2] + + @classmethod + def clear_cache(cls): + """ + Delete all cache keys from database. + Should only be run when all instances are down and all entries thus stale. + """ + cls.query().delete() + Session().commit() + + @classmethod + def _get_cache_key(cls, key): + """ + Wrapper for generating a unique cache key for this instance and "key". + key must / will start with a repo_name which will be stored in .cache_args . + """ + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') + return "%s%s" % (prefix, key) + + @classmethod + def set_invalidate(cls, repo_name, delete=False): + """ + Mark all caches of a repo as invalid in the database. + """ + inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all() + + try: + for inv_obj in inv_objs: + log.debug('marking %s key for invalidation based on repo_name=%s' + % (inv_obj, safe_str(repo_name))) + if delete: + Session().delete(inv_obj) + else: + inv_obj.cache_active = False + Session().add(inv_obj) + Session().commit() + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + + @classmethod + def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None): + """ + Mark this cache key as active and currently cached. + Return True if the existing cache registration still was valid. + Return False to indicate that it had been invalidated and caches should be refreshed. + """ + + key = (repo_name + '_' + kind) if kind else repo_name + cache_key = cls._get_cache_key(key) + + if valid_cache_keys and cache_key in valid_cache_keys: + return True + + try: + inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar() + if not inv_obj: + inv_obj = CacheInvalidation(cache_key, repo_name) + was_valid = inv_obj.cache_active + inv_obj.cache_active = True + Session().add(inv_obj) + Session().commit() + return was_valid + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + return False + + @classmethod + def get_valid_cache_keys(cls): + """ + Return opaque object with information of which caches still are valid + and can be used without checking for invalidation. + """ + return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all()) + + +class ChangesetComment(Base, BaseModel): + __tablename__ = 'changeset_comments' + __table_args__ = ( + Index('cc_revision_idx', 'revision'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + revision = Column('revision', String(40), nullable=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + line_no = Column('line_no', Unicode(10), nullable=True) + hl_lines = Column('hl_lines', Unicode(512), nullable=True) + f_path = Column('f_path', Unicode(1000), nullable=True) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) + text = Column('text', UnicodeText(25000), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan") + pull_request = relationship('PullRequest', lazy='joined') + + @classmethod + def get_users(cls, revision=None, pull_request_id=None): + """ + Returns user associated with this ChangesetComment. ie those + who actually commented + + :param cls: + :param revision: + """ + q = Session().query(User)\ + .join(ChangesetComment.author) + if revision: + q = q.filter(cls.revision == revision) + elif pull_request_id: + q = q.filter(cls.pull_request_id == pull_request_id) + return q.all() + + +class ChangesetStatus(Base, BaseModel): + __tablename__ = 'changeset_statuses' + __table_args__ = ( + Index('cs_revision_idx', 'revision'), + Index('cs_version_idx', 'version'), + UniqueConstraint('repo_id', 'revision', 'version'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed' + STATUS_APPROVED = 'approved' + STATUS_REJECTED = 'rejected' + STATUS_UNDER_REVIEW = 'under_review' + + STATUSES = [ + (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default + (STATUS_APPROVED, _("Approved")), + (STATUS_REJECTED, _("Rejected")), + (STATUS_UNDER_REVIEW, _("Under Review")), + ] + + changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + revision = Column('revision', String(40), nullable=False) + status = Column('status', String(128), nullable=False, default=DEFAULT) + changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id')) + modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now) + version = Column('version', Integer(), nullable=False, default=0) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + comment = relationship('ChangesetComment', lazy='joined') + pull_request = relationship('PullRequest', lazy='joined') + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, + self.status, self.author + ) + + @classmethod + def get_status_lbl(cls, value): + return dict(cls.STATUSES).get(value) + + @property + def status_lbl(self): + return ChangesetStatus.get_status_lbl(self.status) + + +class PullRequest(Base, BaseModel): + __tablename__ = 'pull_requests' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + # values for .status + STATUS_NEW = u'new' + STATUS_OPEN = u'open' + STATUS_CLOSED = u'closed' + + pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) + title = Column('title', Unicode(256), nullable=True) + description = Column('description', UnicodeText(10240), nullable=True) + status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW) # only for closedness, not approve/reject/etc + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max + org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + org_ref = Column('org_ref', Unicode(256), nullable=False) + other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + other_ref = Column('other_ref', Unicode(256), nullable=False) + + @hybrid_property + def revisions(self): + return self._revisions.split(':') + + @revisions.setter + def revisions(self, val): + self._revisions = ':'.join(val) + + @property + def org_ref_parts(self): + return self.org_ref.split(':') + + @property + def other_ref_parts(self): + return self.other_ref.split(':') + + author = relationship('User', lazy='joined') + reviewers = relationship('PullRequestReviewers', + cascade="all, delete, delete-orphan") + org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') + other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id') + statuses = relationship('ChangesetStatus') + comments = relationship('ChangesetComment', + cascade="all, delete, delete-orphan") + + def is_closed(self): + return self.status == self.STATUS_CLOSED + + @property + def last_review_status(self): + return self.statuses[-1].status if self.statuses else '' + + def __json__(self): + return dict( + revisions=self.revisions + ) + + +class PullRequestReviewers(Base, BaseModel): + __tablename__ = 'pull_request_reviewers' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + def __init__(self, user=None, pull_request=None): + self.user = user + self.pull_request = pull_request + + pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True) + + user = relationship('User') + pull_request = relationship('PullRequest') + + +class Notification(Base, BaseModel): + __tablename__ = 'notifications' + __table_args__ = ( + Index('notification_type_idx', 'type'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + TYPE_CHANGESET_COMMENT = u'cs_comment' + TYPE_MESSAGE = u'message' + TYPE_MENTION = u'mention' + TYPE_REGISTRATION = u'registration' + TYPE_PULL_REQUEST = u'pull_request' + TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' + + notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) + subject = Column('subject', Unicode(512), nullable=True) + body = Column('body', UnicodeText(50000), nullable=True) + created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + type_ = Column('type', Unicode(256)) + + created_by_user = relationship('User') + notifications_to_users = relationship('UserNotification', lazy='joined', + cascade="all, delete, delete-orphan") + + @property + def recipients(self): + return [x.user for x in UserNotification.query()\ + .filter(UserNotification.notification == self)\ + .order_by(UserNotification.user_id.asc()).all()] + + @classmethod + def create(cls, created_by, subject, body, recipients, type_=None): + if type_ is None: + type_ = Notification.TYPE_MESSAGE + + notification = cls() + notification.created_by_user = created_by + notification.subject = subject + notification.body = body + notification.type_ = type_ + notification.created_on = datetime.datetime.now() + + for u in recipients: + assoc = UserNotification() + assoc.notification = notification + u.notifications.append(assoc) + Session().add(notification) + return notification + + @property + def description(self): + from kallithea.model.notification import NotificationModel + return NotificationModel().make_description(self) + + +class UserNotification(Base, BaseModel): + __tablename__ = 'user_to_notification' + __table_args__ = ( + UniqueConstraint('user_id', 'notification_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True) + notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True) + read = Column('read', Boolean, default=False) + sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None) + + user = relationship('User', lazy="joined") + notification = relationship('Notification', lazy="joined", + order_by=lambda: Notification.created_on.desc(),) + + def mark_as_read(self): + self.read = True + Session().add(self) + + +class Gist(Base, BaseModel): + __tablename__ = 'gists' + __table_args__ = ( + Index('g_gist_access_id_idx', 'gist_access_id'), + Index('g_created_on_idx', 'created_on'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + GIST_PUBLIC = u'public' + GIST_PRIVATE = u'private' + + gist_id = Column('gist_id', Integer(), primary_key=True) + gist_access_id = Column('gist_access_id', Unicode(250)) + gist_description = Column('gist_description', UnicodeText(1024)) + gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True) + gist_expires = Column('gist_expires', Float(53), nullable=False) + gist_type = Column('gist_type', Unicode(128), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + owner = relationship('User') + + @classmethod + def get_or_404(cls, id_): + res = cls.query().filter(cls.gist_access_id == id_).scalar() + if not res: + raise HTTPNotFound + return res + + @classmethod + def get_by_access_id(cls, gist_access_id): + return cls.query().filter(cls.gist_access_id == gist_access_id).scalar() + + def gist_url(self): + import kallithea + alias_url = kallithea.CONFIG.get('gist_alias_url') + if alias_url: + return alias_url.replace('{gistid}', self.gist_access_id) + + from pylons import url + return url('gist', gist_id=self.gist_access_id, qualified=True) + + @classmethod + def base_path(cls): + """ + Returns base path when all gists are stored + + :param cls: + """ + from kallithea.model.gist import GIST_STORE_LOC + q = Session().query(Ui)\ + .filter(Ui.ui_key == URL_SEP) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return os.path.join(q.one().ui_value, GIST_STORE_LOC) + + def get_api_data(self): + """ + Common function for generating gist related data for API + """ + gist = self + data = dict( + gist_id=gist.gist_id, + type=gist.gist_type, + access_id=gist.gist_access_id, + description=gist.gist_description, + url=gist.gist_url(), + expires=gist.gist_expires, + created_on=gist.created_on, + ) + return data + + def __json__(self): + data = dict( + ) + data.update(self.get_api_data()) + return data + ## SCM functions + + @property + def scm_instance(self): + from kallithea.lib.vcs import get_repo + base_path = self.base_path() + return get_repo(os.path.join(*map(safe_str, + [base_path, self.gist_access_id]))) + + +class DbMigrateVersion(Base, BaseModel): + __tablename__ = 'db_migrate_version' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + repository_id = Column('repository_id', String(250), primary_key=True) + repository_path = Column('repository_path', Text) + version = Column('version', Integer) diff --git a/kallithea/lib/dbmigrate/schema/db_2_0_2.py b/kallithea/lib/dbmigrate/schema/db_2_0_2.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/schema/db_2_0_2.py @@ -0,0 +1,2356 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.db +~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import os +import time +import logging +import datetime +import traceback +import hashlib +import collections +import functools + +from sqlalchemy import * +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import relationship, joinedload, class_mapper, validates +from sqlalchemy.exc import DatabaseError +from beaker.cache import cache_region, region_invalidate +from webob.exc import HTTPNotFound + +from pylons.i18n.translation import lazy_ugettext as _ + +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset + +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ + safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache + +from kallithea.model.meta import Base, Session + +URL_SEP = '/' +log = logging.getLogger(__name__) + +from kallithea import DB_PREFIX + +#============================================================================== +# BASE CLASSES +#============================================================================== + +_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest() + + +class BaseModel(object): + """ + Base Model for all classess + """ + + @classmethod + def _get_keys(cls): + """return column names for this model """ + return class_mapper(cls).c.keys() + + def get_dict(self): + """ + return dict with keys and values corresponding + to this model data """ + + d = {} + for k in self._get_keys(): + d[k] = getattr(self, k) + + # also use __json__() if present to get additional fields + _json_attr = getattr(self, '__json__', None) + if _json_attr: + # update with attributes from __json__ + if callable(_json_attr): + _json_attr = _json_attr() + for k, val in _json_attr.iteritems(): + d[k] = val + return d + + def get_appstruct(self): + """return list with keys and values tupples corresponding + to this model data """ + + l = [] + for k in self._get_keys(): + l.append((k, getattr(self, k),)) + return l + + def populate_obj(self, populate_dict): + """populate model with data from given populate_dict""" + + for k in self._get_keys(): + if k in populate_dict: + setattr(self, k, populate_dict[k]) + + @classmethod + def query(cls): + return Session().query(cls) + + @classmethod + def get(cls, id_): + if id_: + return cls.query().get(id_) + + @classmethod + def get_or_404(cls, id_): + try: + id_ = int(id_) + except (TypeError, ValueError): + raise HTTPNotFound + + res = cls.query().get(id_) + if not res: + raise HTTPNotFound + return res + + @classmethod + def getAll(cls): + # deprecated and left for backward compatibility + return cls.get_all() + + @classmethod + def get_all(cls): + return cls.query().all() + + @classmethod + def delete(cls, id_): + obj = cls.query().get(id_) + Session().delete(obj) + + def __repr__(self): + if hasattr(self, '__unicode__'): + # python repr needs to return str + try: + return safe_str(self.__unicode__()) + except UnicodeDecodeError: + pass + return '' % (self.__class__.__name__) + + +class Setting(Base, BaseModel): + SETTINGS_TYPES = { + 'str': safe_str, + 'int': safe_int, + 'unicode': safe_unicode, + 'bool': str2bool, + 'list': functools.partial(aslist, sep=',') + } + __tablename__ = DB_PREFIX + 'settings' + __table_args__ = ( + UniqueConstraint('app_settings_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + app_settings_name = Column("app_settings_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_value = Column("app_settings_value", String(4096, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_type = Column("app_settings_type", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __init__(self, key='', val='', type='unicode'): + self.app_settings_name = key + self.app_settings_value = val + self.app_settings_type = type + + @validates('_app_settings_value') + def validate_settings_value(self, key, val): + assert type(val) == unicode + return val + + @hybrid_property + def app_settings_value(self): + v = self._app_settings_value + _type = self.app_settings_type + converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode'] + return converter(v) + + @app_settings_value.setter + def app_settings_value(self, val): + """ + Setter that will always make sure we use unicode in app_settings_value + + :param val: + """ + self._app_settings_value = safe_unicode(val) + + @hybrid_property + def app_settings_type(self): + return self._app_settings_type + + @app_settings_type.setter + def app_settings_type(self, val): + if val not in self.SETTINGS_TYPES: + raise Exception('type must be one of %s got %s' + % (self.SETTINGS_TYPES.keys(), val)) + self._app_settings_type = val + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % ( + self.__class__.__name__, + self.app_settings_name, self.app_settings_value, self.app_settings_type + ) + + @classmethod + def get_by_name(cls, key): + return cls.query()\ + .filter(cls.app_settings_name == key).scalar() + + @classmethod + def get_by_name_or_create(cls, key, val='', type='unicode'): + res = cls.get_by_name(key) + if not res: + res = cls(key, val, type) + return res + + @classmethod + def create_or_update(cls, key, val=Optional(''), type=Optional('unicode')): + """ + Creates or updates Kallithea setting. If updates is triggered it will only + update parameters that are explicityl set Optional instance will be skipped + + :param key: + :param val: + :param type: + :return: + """ + res = cls.get_by_name(key) + if not res: + val = Optional.extract(val) + type = Optional.extract(type) + res = cls(key, val, type) + else: + res.app_settings_name = key + if not isinstance(val, Optional): + # update if set + res.app_settings_value = val + if not isinstance(type, Optional): + # update if set + res.app_settings_type = type + return res + + @classmethod + def get_app_settings(cls, cache=False): + + ret = cls.query() + + if cache: + ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) + + if not ret: + raise Exception('Could not get application settings !') + settings = {} + for each in ret: + settings[each.app_settings_name] = \ + each.app_settings_value + + return settings + + @classmethod + def get_auth_plugins(cls, cache=False): + auth_plugins = cls.get_by_name("auth_plugins").app_settings_value + return auth_plugins + + @classmethod + def get_auth_settings(cls, cache=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('auth_')).all() + fd = {} + for row in ret: + fd.update({row.app_settings_name: row.app_settings_value}) + + return fd + + @classmethod + def get_default_repo_settings(cls, cache=False, strip_prefix=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('default_')).all() + fd = {} + for row in ret: + key = row.app_settings_name + if strip_prefix: + key = remove_prefix(key, prefix='default_') + fd.update({key: row.app_settings_value}) + + return fd + + @classmethod + def get_server_info(cls): + import pkg_resources + import platform + import kallithea + from kallithea.lib.utils import check_git_version + mods = [(p.project_name, p.version) for p in pkg_resources.working_set] + info = { + 'modules': sorted(mods, key=lambda k: k[0].lower()), + 'py_version': platform.python_version(), + 'platform': safe_unicode(platform.platform()), + 'kallithea_version': kallithea.__version__, + 'git_version': safe_unicode(check_git_version()), + 'git_path': kallithea.CONFIG.get('git_path') + } + return info + + +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' + __table_args__ = ( + UniqueConstraint('ui_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + HOOK_UPDATE = 'changegroup.update' + HOOK_REPO_SIZE = 'changegroup.repo_size' + HOOK_PUSH = 'changegroup.push_logger' + HOOK_PRE_PUSH = 'prechangegroup.pre_push' + HOOK_PULL = 'outgoing.pull_logger' + HOOK_PRE_PULL = 'preoutgoing.pre_pull' + + ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) + + # def __init__(self, section='', key='', value=''): + # self.ui_section = section + # self.ui_key = key + # self.ui_value = value + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.ui_key == key).scalar() + + @classmethod + def get_builtin_hooks(cls): + q = cls.query() + q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + return q.all() + + @classmethod + def get_custom_hooks(cls): + q = cls.query() + q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + q = q.filter(cls.ui_section == 'hooks') + return q.all() + + @classmethod + def get_repos_location(cls): + return cls.get_by_key('/').ui_value + + @classmethod + def create_or_update_hook(cls, key, val): + new_ui = cls.get_by_key(key) or cls() + new_ui.ui_section = 'hooks' + new_ui.ui_active = True + new_ui.ui_key = key + new_ui.ui_value = val + + Session().add(new_ui) + + def __repr__(self): + return '' % (self.__class__.__name__, self.ui_key, + self.ui_value) + + +class User(Base, BaseModel): + __tablename__ = 'users' + __table_args__ = ( + UniqueConstraint('username'), UniqueConstraint('email'), + Index('u_username_idx', 'username'), + Index('u_email_idx', 'email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + DEFAULT_USER = 'default' + + user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + admin = Column("admin", Boolean(), nullable=True, unique=None, default=False) + name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) + extern_type = Column("extern_type", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + extern_name = Column("extern_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + user_log = relationship('UserLog') + user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') + + repositories = relationship('Repository') + user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all') + followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all') + + repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all') + repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all') + + group_member = relationship('UserGroupMember', cascade='all') + + notifications = relationship('UserNotification', cascade='all') + # notifications assigned to this user + user_created_notifications = relationship('Notification', cascade='all') + # comments created by this user + user_comments = relationship('ChangesetComment', cascade='all') + #extra emails for this user + user_emails = relationship('UserEmailMap', cascade='all') + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + @property + def firstname(self): + # alias for future + return self.name + + @property + def emails(self): + other = UserEmailMap.query().filter(UserEmailMap.user==self).all() + return [self.email] + [x.email for x in other] + + @property + def ip_addresses(self): + ret = UserIpMap.query().filter(UserIpMap.user == self).all() + return [x.ip_addr for x in ret] + + @property + def username_and_name(self): + return '%s (%s %s)' % (self.username, self.firstname, self.lastname) + + @property + def full_name(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def full_name_or_username(self): + return ('%s %s' % (self.firstname, self.lastname) + if (self.firstname and self.lastname) else self.username) + + @property + def full_contact(self): + return '%s %s <%s>' % (self.firstname, self.lastname, self.email) + + @property + def short_contact(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def is_admin(self): + return self.admin + + @property + def AuthUser(self): + """ + Returns instance of AuthUser for this user + """ + from kallithea.lib.auth import AuthUser + return AuthUser(user_id=self.user_id, api_key=self.api_key, + username=self.username) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.user_id, self.username) + + @classmethod + def get_by_username(cls, username, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.username.ilike(username)) + else: + q = cls.query().filter(cls.username == username) + + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(username) + ) + ) + return q.scalar() + + @classmethod + def get_by_api_key(cls, api_key, cache=False): + q = cls.query().filter(cls.api_key == api_key) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_api_key_%s" % api_key)) + return q.scalar() + + @classmethod + def get_by_email(cls, email, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.email.ilike(email)) + else: + q = cls.query().filter(cls.email == email) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_key_%s" % email)) + + ret = q.scalar() + if ret is None: + q = UserEmailMap.query() + # try fetching in alternate email map + if case_insensitive: + q = q.filter(UserEmailMap.email.ilike(email)) + else: + q = q.filter(UserEmailMap.email == email) + q = q.options(joinedload(UserEmailMap.user)) + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_map_key_%s" % email)) + ret = getattr(q.scalar(), 'user', None) + + return ret + + @classmethod + def get_from_cs_author(cls, author): + """ + Tries to get User objects out of commit author string + + :param author: + """ + from kallithea.lib.helpers import email, author_name + # Valid email in the attribute passed, see if they're in the system + _email = email(author) + if _email: + user = cls.get_by_email(_email, case_insensitive=True) + if user: + return user + # Maybe we can match by username? + _author = author_name(author) + user = cls.get_by_username(_author, case_insensitive=True) + if user: + return user + + def update_lastlogin(self): + """Update user lastlogin""" + self.last_login = datetime.datetime.now() + Session().add(self) + log.debug('updated user %s lastlogin' % self.username) + + @classmethod + def get_first_admin(cls): + user = User.query().filter(User.admin == True).first() + if user is None: + raise Exception('Missing administrative account!') + return user + + @classmethod + def get_default_user(cls, cache=False): + user = User.get_by_username(User.DEFAULT_USER, cache=cache) + if user is None: + raise Exception('Missing default account!') + return user + + def get_api_data(self): + """ + Common function for generating user related data for API + """ + user = self + data = dict( + user_id=user.user_id, + username=user.username, + firstname=user.name, + lastname=user.lastname, + email=user.email, + emails=user.emails, + api_key=user.api_key, + active=user.active, + admin=user.admin, + extern_type=user.extern_type, + extern_name=user.extern_name, + last_login=user.last_login, + ip_addresses=user.ip_addresses + ) + return data + + def __json__(self): + data = dict( + full_name=self.full_name, + full_name_or_username=self.full_name_or_username, + short_contact=self.short_contact, + full_contact=self.full_contact + ) + data.update(self.get_api_data()) + return data + + +class UserEmailMap(Base, BaseModel): + __tablename__ = 'user_email_map' + __table_args__ = ( + Index('uem_email_idx', 'email'), + UniqueConstraint('email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + user = relationship('User', lazy='joined') + + @validates('_email') + def validate_email(self, key, email): + # check if this email is not main one + main_email = Session().query(User).filter(User.email == email).scalar() + if main_email is not None: + raise AttributeError('email %s is present is user table' % email) + return email + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + +class UserIpMap(Base, BaseModel): + __tablename__ = 'user_ip_map' + __table_args__ = ( + UniqueConstraint('user_id', 'ip_addr'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + user = relationship('User', lazy='joined') + + @classmethod + def _get_ip_range(cls, ip_addr): + from kallithea.lib import ipaddr + net = ipaddr.IPNetwork(address=ip_addr) + return [str(net.network), str(net.broadcast)] + + def __json__(self): + return dict( + ip_addr=self.ip_addr, + ip_range=self._get_ip_range(self.ip_addr) + ) + + +class UserLog(Base, BaseModel): + __tablename__ = 'user_logs' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True) + repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.repository_name, + self.action) + + @property + def action_as_day(self): + return datetime.date(*self.action_date.timetuple()[:3]) + + user = relationship('User') + repository = relationship('Repository', cascade='') + + +class UserGroup(Base, BaseModel): + __tablename__ = 'users_groups' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + user_group_description = Column("user_group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined") + users_group_to_perm = relationship('UserGroupToPerm', cascade='all') + users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all') + user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all') + + user = relationship('User') + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.users_group_id, + self.users_group_name) + + @classmethod + def get_by_group_name(cls, group_name, cache=False, + case_insensitive=False): + if case_insensitive: + q = cls.query().filter(cls.users_group_name.ilike(group_name)) + else: + q = cls.query().filter(cls.users_group_name == group_name) + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(group_name) + ) + ) + return q.scalar() + + @classmethod + def get(cls, user_group_id, cache=False): + user_group = cls.query() + if cache: + user_group = user_group.options(FromCache("sql_cache_short", + "get_users_group_%s" % user_group_id)) + return user_group.get(user_group_id) + + def get_api_data(self, with_members=True): + user_group = self + + data = dict( + users_group_id=user_group.users_group_id, + group_name=user_group.users_group_name, + group_description=user_group.user_group_description, + active=user_group.users_group_active, + owner=user_group.user.username, + ) + if with_members: + members = [] + for user in user_group.members: + user = user.user + members.append(user.get_api_data()) + data['members'] = members + + return data + + +class UserGroupMember(Base, BaseModel): + __tablename__ = 'users_groups_members' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + + user = relationship('User', lazy='joined') + users_group = relationship('UserGroup') + + def __init__(self, gr_id='', u_id=''): + self.users_group_id = gr_id + self.user_id = u_id + + +class RepositoryField(Base, BaseModel): + __tablename__ = 'repositories_fields' + __table_args__ = ( + UniqueConstraint('repository_id', 'field_key'), # no-multi field + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields + + repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + field_key = Column("field_key", String(250, convert_unicode=False, assert_unicode=None)) + field_label = Column("field_label", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_value = Column("field_value", String(10000, convert_unicode=False, assert_unicode=None), nullable=False) + field_desc = Column("field_desc", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_type = Column("field_type", String(256), nullable=False, unique=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repository = relationship('Repository') + + @property + def field_key_prefixed(self): + return 'ex_%s' % self.field_key + + @classmethod + def un_prefix_key(cls, key): + if key.startswith(cls.PREFIX): + return key[len(cls.PREFIX):] + return key + + @classmethod + def get_by_key_name(cls, key, repo): + row = cls.query()\ + .filter(cls.repository == repo)\ + .filter(cls.field_key == key).scalar() + return row + + +class Repository(Base, BaseModel): + __tablename__ = 'repositories' + __table_args__ = ( + UniqueConstraint('repo_name'), + Index('r_repo_name_idx', 'repo_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + private = Column("private", Boolean(), nullable=True, unique=None, default=None) + enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True) + enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True) + description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + _landing_revision = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data + + fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) + + user = relationship('User') + fork = relationship('Repository', remote_side=repo_id) + group = relationship('RepoGroup') + repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + stats = relationship('Statistics', cascade='all', uselist=False) + + followers = relationship('UserFollowing', + primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', + cascade='all') + extra_fields = relationship('RepositoryField', + cascade="all, delete, delete-orphan") + + logs = relationship('UserLog') + comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan") + + pull_requests_org = relationship('PullRequest', + primaryjoin='PullRequest.org_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + pull_requests_other = relationship('PullRequest', + primaryjoin='PullRequest.other_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, + safe_unicode(self.repo_name)) + + @hybrid_property + def landing_rev(self): + # always should return [rev_type, rev] + if self._landing_revision: + _rev_info = self._landing_revision.split(':') + if len(_rev_info) < 2: + _rev_info.insert(0, 'rev') + return [_rev_info[0], _rev_info[1]] + return [None, None] + + @landing_rev.setter + def landing_rev(self, val): + if ':' not in val: + raise ValueError('value must be delimited with `:` and consist ' + 'of :, got %s instead' % val) + self._landing_revision = val + + @hybrid_property + def locked(self): + # always should return [user_id, timelocked] + if self._locked: + _lock_info = self._locked.split(':') + return int(_lock_info[0]), _lock_info[1] + return [None, None] + + @locked.setter + def locked(self, val): + if val and isinstance(val, (list, tuple)): + self._locked = ':'.join(map(str, val)) + else: + self._locked = None + + @hybrid_property + def changeset_cache(self): + from kallithea.lib.vcs.backends.base import EmptyChangeset + dummy = EmptyChangeset().__json__() + if not self._changeset_cache: + return dummy + try: + return json.loads(self._changeset_cache) + except TypeError: + return dummy + + @changeset_cache.setter + def changeset_cache(self, val): + try: + self._changeset_cache = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def normalize_repo_name(cls, repo_name): + """ + Normalizes os specific repo_name to the format internally stored inside + dabatabase using URL_SEP + + :param cls: + :param repo_name: + """ + return cls.url_sep().join(repo_name.split(os.sep)) + + @classmethod + def get_by_repo_name(cls, repo_name): + q = Session().query(cls).filter(cls.repo_name == repo_name) + q = q.options(joinedload(Repository.fork))\ + .options(joinedload(Repository.user))\ + .options(joinedload(Repository.group)) + return q.scalar() + + @classmethod + def get_by_full_path(cls, repo_full_path): + repo_name = repo_full_path.split(cls.base_path(), 1)[-1] + repo_name = cls.normalize_repo_name(repo_name) + return cls.get_by_repo_name(repo_name.strip(URL_SEP)) + + @classmethod + def get_repo_forks(cls, repo_id): + return cls.query().filter(Repository.fork_id == repo_id) + + @classmethod + def base_path(cls): + """ + Returns base path when all repos are stored + + :param cls: + """ + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def forks(self): + """ + Return forks of this repo + """ + return Repository.get_repo_forks(self.repo_id) + + @property + def parent(self): + """ + Returns fork parent + """ + return self.fork + + @property + def just_name(self): + return self.repo_name.split(Repository.url_sep())[-1] + + @property + def groups_with_parents(self): + groups = [] + if self.group is None: + return groups + + cur_gr = self.group + groups.insert(0, cur_gr) + while 1: + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + groups.insert(0, gr) + + return groups + + @property + def groups_and_repo(self): + return self.groups_with_parents, self.just_name, self.repo_name + + @LazyProperty + def repo_path(self): + """ + Returns base full path for that repository means where it actually + exists on a filesystem + """ + q = Session().query(Ui).filter(Ui.ui_key == + Repository.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def repo_full_path(self): + p = [self.repo_path] + # we need to split the name by / since this is how we store the + # names in the database, but that eventually needs to be converted + # into a valid system path + p += self.repo_name.split(Repository.url_sep()) + return os.path.join(*map(safe_unicode, p)) + + @property + def cache_keys(self): + """ + Returns associated cache keys for that repo + """ + return CacheInvalidation.query()\ + .filter(CacheInvalidation.cache_args == self.repo_name)\ + .order_by(CacheInvalidation.cache_key)\ + .all() + + def get_new_name(self, repo_name): + """ + returns new full repository name based on assigned group and new new + + :param group_name: + """ + path_prefix = self.group.full_path_splitted if self.group else [] + return Repository.url_sep().join(path_prefix + [repo_name]) + + @property + def _ui(self): + """ + Creates an db based ui object for this repository + """ + from kallithea.lib.utils import make_ui + return make_ui('db', clear_session=False) + + @classmethod + def is_valid(cls, repo_name): + """ + returns True if given repo name is a valid filesystem repository + + :param cls: + :param repo_name: + """ + from kallithea.lib.utils import is_valid_repo + + return is_valid_repo(repo_name, cls.base_path()) + + def get_api_data(self): + """ + Common function for generating repo api data + + """ + repo = self + data = dict( + repo_id=repo.repo_id, + repo_name=repo.repo_name, + repo_type=repo.repo_type, + clone_uri=repo.clone_uri, + private=repo.private, + created_on=repo.created_on, + description=repo.description, + landing_rev=repo.landing_rev, + owner=repo.user.username, + fork_of=repo.fork.repo_name if repo.fork else None, + enable_statistics=repo.enable_statistics, + enable_locking=repo.enable_locking, + enable_downloads=repo.enable_downloads, + last_changeset=repo.changeset_cache, + locked_by=User.get(self.locked[0]).get_api_data() \ + if self.locked[0] else None, + locked_date=time_to_datetime(self.locked[1]) \ + if self.locked[1] else None + ) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) + if repository_fields: + for f in self.extra_fields: + data[f.field_key_prefixed] = f.field_value + + return data + + @classmethod + def lock(cls, repo, user_id, lock_time=None): + if not lock_time: + lock_time = time.time() + repo.locked = [user_id, lock_time] + Session().add(repo) + Session().commit() + + @classmethod + def unlock(cls, repo): + repo.locked = None + Session().add(repo) + Session().commit() + + @classmethod + def getlock(cls, repo): + return repo.locked + + @property + def last_db_change(self): + return self.updated_on + + def clone_url(self, **override): + from pylons import url + from urlparse import urlparse + import urllib + parsed_url = urlparse(url('home', qualified=True)) + default_clone_uri = '%(scheme)s://%(user)s%(pass)s%(netloc)s%(prefix)s%(path)s' + decoded_path = safe_unicode(urllib.unquote(parsed_url.path)) + args = { + 'user': '', + 'pass': '', + 'scheme': parsed_url.scheme, + 'netloc': parsed_url.netloc, + 'prefix': decoded_path, + 'path': self.repo_name + } + + args.update(override) + return default_clone_uri % args + + #========================================================================== + # SCM PROPERTIES + #========================================================================== + + def get_changeset(self, rev=None): + return get_changeset_safe(self.scm_instance, rev) + + def get_landing_changeset(self): + """ + Returns landing changeset, or if that doesn't exist returns the tip + """ + _rev_type, _rev = self.landing_rev + cs = self.get_changeset(_rev) + if isinstance(cs, EmptyChangeset): + return self.get_changeset() + return cs + + def update_changeset_cache(self, cs_cache=None): + """ + Update cache of last changeset for repository, keys should be:: + + short_id + raw_id + revision + message + date + author + + :param cs_cache: + """ + from kallithea.lib.vcs.backends.base import BaseChangeset + if cs_cache is None: + cs_cache = EmptyChangeset() + # use no-cache version here + scm_repo = self.scm_instance_no_cache() + if scm_repo: + cs_cache = scm_repo.get_changeset() + + if isinstance(cs_cache, BaseChangeset): + cs_cache = cs_cache.__json__() + + if (cs_cache != self.changeset_cache or not self.changeset_cache): + _default = datetime.datetime.fromtimestamp(0) + last_change = cs_cache.get('date') or _default + log.debug('updated repo %s with new cs cache %s' + % (self.repo_name, cs_cache)) + self.updated_on = last_change + self.changeset_cache = cs_cache + Session().add(self) + Session().commit() + else: + log.debug('Skipping repo:%s already with latest changes' + % self.repo_name) + + @property + def tip(self): + return self.get_changeset('tip') + + @property + def author(self): + return self.tip.author + + @property + def last_change(self): + return self.scm_instance.last_change + + def get_comments(self, revisions=None): + """ + Returns comments for this repository grouped by revisions + + :param revisions: filter query by revisions only + """ + cmts = ChangesetComment.query()\ + .filter(ChangesetComment.repo == self) + if revisions: + cmts = cmts.filter(ChangesetComment.revision.in_(revisions)) + grouped = collections.defaultdict(list) + for cmt in cmts.all(): + grouped[cmt.revision].append(cmt) + return grouped + + def statuses(self, revisions=None): + """ + Returns statuses for this repository + + :param revisions: list of revisions to get statuses for + """ + + statuses = ChangesetStatus.query()\ + .filter(ChangesetStatus.repo == self)\ + .filter(ChangesetStatus.version == 0) + if revisions: + statuses = statuses.filter(ChangesetStatus.revision.in_(revisions)) + grouped = {} + + #maybe we have open new pullrequest without a status ? + stat = ChangesetStatus.STATUS_UNDER_REVIEW + status_lbl = ChangesetStatus.get_status_lbl(stat) + for pr in PullRequest.query().filter(PullRequest.org_repo == self).all(): + for rev in pr.revisions: + pr_id = pr.pull_request_id + pr_repo = pr.other_repo.repo_name + grouped[rev] = [stat, status_lbl, pr_id, pr_repo] + + for stat in statuses.all(): + pr_id = pr_repo = None + if stat.pull_request: + pr_id = stat.pull_request.pull_request_id + pr_repo = stat.pull_request.other_repo.repo_name + grouped[stat.revision] = [str(stat.status), stat.status_lbl, + pr_id, pr_repo] + return grouped + + def _repo_size(self): + from kallithea.lib import helpers as h + log.debug('calculating repository size...') + return h.format_byte_size(self.scm_instance.size) + + #========================================================================== + # SCM CACHE INSTANCE + #========================================================================== + + def set_invalidate(self): + """ + Mark caches of this repo as invalid. + """ + CacheInvalidation.set_invalidate(self.repo_name) + + def scm_instance_no_cache(self): + return self.__get_instance() + + @property + def scm_instance(self): + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) + if full_cache: + return self.scm_instance_cached() + return self.__get_instance() + + def scm_instance_cached(self, valid_cache_keys=None): + @cache_region('long_term') + def _c(repo_name): + return self.__get_instance() + rn = self.repo_name + + valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys) + if not valid: + log.debug('Cache for %s invalidated, getting new object' % (rn)) + region_invalidate(_c, None, rn) + else: + log.debug('Getting obj for %s from cache' % (rn)) + return _c(rn) + + def __get_instance(self): + repo_full_path = self.repo_full_path + try: + alias = get_scm(repo_full_path)[0] + log.debug('Creating instance of %s repository from %s' + % (alias, repo_full_path)) + backend = get_backend(alias) + except VCSError: + log.error(traceback.format_exc()) + log.error('Perhaps this repository is in db and not in ' + 'filesystem run rescan repositories with ' + '"destroy old data " option from admin panel') + return + + if alias == 'hg': + + repo = backend(safe_str(repo_full_path), create=False, + baseui=self._ui) + # skip hidden web repository + if repo._get_hidden(): + return + else: + repo = backend(repo_full_path, create=False) + + return repo + + def __json__(self): + return dict(landing_rev = self.landing_rev) + +class RepoGroup(Base, BaseModel): + __tablename__ = 'groups' + __table_args__ = ( + UniqueConstraint('group_name', 'group_parent_id'), + CheckConstraint('group_id != group_parent_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + __mapper_args__ = {'order_by': 'group_name'} + + group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + group_name = Column("group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) + group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + parent_group = relationship('RepoGroup', remote_side=group_id) + user = relationship('User') + + def __init__(self, group_name='', parent_group=None): + self.group_name = group_name + self.parent_group = parent_group + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id, + self.group_name) + + @classmethod + def groups_choices(cls, groups=None, show_empty_group=True): + from webhelpers.html import literal as _literal + if not groups: + groups = cls.query().all() + + repo_groups = [] + if show_empty_group: + repo_groups = [('-1', u'-- %s --' % _('top level'))] + sep = ' » ' + _name = lambda k: _literal(sep.join(k)) + + repo_groups.extend([(x.group_id, _name(x.full_path_splitted)) + for x in groups]) + + repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0]) + return repo_groups + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): + if case_insensitive: + gr = cls.query()\ + .filter(cls.group_name.ilike(group_name)) + else: + gr = cls.query()\ + .filter(cls.group_name == group_name) + if cache: + gr = gr.options(FromCache( + "sql_cache_short", + "get_group_%s" % _hash_key(group_name) + ) + ) + return gr.scalar() + + @property + def parents(self): + parents_recursion_limit = 5 + groups = [] + if self.parent_group is None: + return groups + cur_gr = self.parent_group + groups.insert(0, cur_gr) + cnt = 0 + while 1: + cnt += 1 + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + if cnt == parents_recursion_limit: + # this will prevent accidental infinit loops + log.error('group nested more than %s' % + parents_recursion_limit) + break + + groups.insert(0, gr) + return groups + + @property + def children(self): + return RepoGroup.query().filter(RepoGroup.parent_group == self) + + @property + def name(self): + return self.group_name.split(RepoGroup.url_sep())[-1] + + @property + def full_path(self): + return self.group_name + + @property + def full_path_splitted(self): + return self.group_name.split(RepoGroup.url_sep()) + + @property + def repositories(self): + return Repository.query()\ + .filter(Repository.group == self)\ + .order_by(Repository.repo_name) + + @property + def repositories_recursive_count(self): + cnt = self.repositories.count() + + def children_count(group): + cnt = 0 + for child in group.children: + cnt += child.repositories.count() + cnt += children_count(child) + return cnt + + return cnt + children_count(self) + + def _recursive_objects(self, include_repos=True): + all_ = [] + + def _get_members(root_gr): + if include_repos: + for r in root_gr.repositories: + all_.append(r) + childs = root_gr.children.all() + if childs: + for gr in childs: + all_.append(gr) + _get_members(gr) + + _get_members(self) + return [self] + all_ + + def recursive_groups_and_repos(self): + """ + Recursive return all groups, with repositories in those groups + """ + return self._recursive_objects() + + def recursive_groups(self): + """ + Returns all children groups for this group including children of children + """ + return self._recursive_objects(include_repos=False) + + def get_new_name(self, group_name): + """ + returns new full group name based on parent and new name + + :param group_name: + """ + path_prefix = (self.parent_group.full_path_splitted if + self.parent_group else []) + return RepoGroup.url_sep().join(path_prefix + [group_name]) + + def get_api_data(self): + """ + Common function for generating api data + + """ + group = self + data = dict( + group_id=group.group_id, + group_name=group.group_name, + group_description=group.group_description, + parent_group=group.parent_group.group_name if group.parent_group else None, + repositories=[x.repo_name for x in group.repositories], + owner=group.user.username + ) + return data + + +class Permission(Base, BaseModel): + __tablename__ = 'permissions' + __table_args__ = ( + Index('p_perm_name_idx', 'permission_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PERMS = [ + ('hg.admin', _('Kallithea Administrator')), + + ('repository.none', _('Repository no access')), + ('repository.read', _('Repository read access')), + ('repository.write', _('Repository write access')), + ('repository.admin', _('Repository admin access')), + + ('group.none', _('Repository group no access')), + ('group.read', _('Repository group read access')), + ('group.write', _('Repository group write access')), + ('group.admin', _('Repository group admin access')), + + ('usergroup.none', _('User group no access')), + ('usergroup.read', _('User group read access')), + ('usergroup.write', _('User group write access')), + ('usergroup.admin', _('User group admin access')), + + ('hg.repogroup.create.false', _('Repository Group creation disabled')), + ('hg.repogroup.create.true', _('Repository Group creation enabled')), + + ('hg.usergroup.create.false', _('User Group creation disabled')), + ('hg.usergroup.create.true', _('User Group creation enabled')), + + ('hg.create.none', _('Repository creation disabled')), + ('hg.create.repository', _('Repository creation enabled')), + + ('hg.fork.none', _('Repository forking disabled')), + ('hg.fork.repository', _('Repository forking enabled')), + + ('hg.register.none', _('Registration disabled')), + ('hg.register.manual_activate', _('User Registration with manual account activation')), + ('hg.register.auto_activate', _('User Registration with automatic account activation')), + + ('hg.extern_activate.manual', _('Manual activation of external account')), + ('hg.extern_activate.auto', _('Automatic activation of external account')), + + ] + + #definition of system default permissions for DEFAULT user + DEFAULT_USER_PERMISSIONS = [ + 'repository.read', + 'group.read', + 'usergroup.read', + 'hg.create.repository', + 'hg.fork.repository', + 'hg.register.manual_activate', + 'hg.extern_activate.auto', + ] + + # defines which permissions are more important higher the more important + # Weight defines which permissions are more important. + # The higher number the more important. + PERM_WEIGHTS = { + 'repository.none': 0, + 'repository.read': 1, + 'repository.write': 3, + 'repository.admin': 4, + + 'group.none': 0, + 'group.read': 1, + 'group.write': 3, + 'group.admin': 4, + + 'usergroup.none': 0, + 'usergroup.read': 1, + 'usergroup.write': 3, + 'usergroup.admin': 4, + 'hg.repogroup.create.false': 0, + 'hg.repogroup.create.true': 1, + + 'hg.usergroup.create.false': 0, + 'hg.usergroup.create.true': 1, + + 'hg.fork.none': 0, + 'hg.fork.repository': 1, + 'hg.create.none': 0, + 'hg.create.repository': 1 + } + + permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, self.permission_id, self.permission_name + ) + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.permission_name == key).scalar() + + @classmethod + def get_default_perms(cls, default_user_id): + q = Session().query(UserRepoToPerm, Repository, cls)\ + .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ + .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_group_perms(cls, default_user_id): + q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\ + .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\ + .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoGroupToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_user_group_perms(cls, default_user_id): + q = Session().query(UserUserGroupToPerm, UserGroup, cls)\ + .join((UserGroup, UserUserGroupToPerm.user_group_id == UserGroup.users_group_id))\ + .join((cls, UserUserGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserUserGroupToPerm.user_id == default_user_id) + + return q.all() + + +class UserRepoToPerm(Base, BaseModel): + __tablename__ = 'repo_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'repository_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + repository = relationship('Repository') + permission = relationship('Permission') + + @classmethod + def create(cls, user, repository, permission): + n = cls() + n.user = user + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.repository) + + +class UserUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'user_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + user_group = relationship('UserGroup') + permission = relationship('Permission') + + @classmethod + def create(cls, user, user_group, permission): + n = cls() + n.user = user + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.user_group) + + +class UserToPerm(Base, BaseModel): + __tablename__ = 'user_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + permission = relationship('Permission', lazy='joined') + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.permission) + + +class UserGroupRepoToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_to_perm' + __table_args__ = ( + UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + repository = relationship('Repository') + + @classmethod + def create(cls, users_group, repository, permission): + n = cls() + n.users_group = users_group + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.users_group, self.repository) + + +class UserGroupUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_group_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'), + CheckConstraint('target_user_group_id != user_group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id') + user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id') + permission = relationship('Permission') + + @classmethod + def create(cls, target_user_group, user_group, permission): + n = cls() + n.target_user_group = target_user_group + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.target_user_group, self.user_group) + + +class UserGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'permission_id',), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + + +class UserRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'user_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + group = relationship('RepoGroup') + permission = relationship('Permission') + + +class UserGroupRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + group = relationship('RepoGroup') + + +class Statistics(Base, BaseModel): + __tablename__ = 'statistics' + __table_args__ = ( + UniqueConstraint('repository_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) + stat_on_revision = Column("stat_on_revision", Integer(), nullable=False) + commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data + commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data + languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data + + repository = relationship('Repository', single_parent=True) + + +class UserFollowing(Base, BaseModel): + __tablename__ = 'user_followings' + __table_args__ = ( + UniqueConstraint('user_id', 'follows_repository_id'), + UniqueConstraint('user_id', 'follows_user_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None) + follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + + user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') + + follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') + follows_repository = relationship('Repository', order_by='Repository.repo_name') + + @classmethod + def get_repo_followers(cls, repo_id): + return cls.query().filter(cls.follows_repo_id == repo_id) + + +class CacheInvalidation(Base, BaseModel): + __tablename__ = 'cache_invalidation' + __table_args__ = ( + UniqueConstraint('cache_key'), + Index('key_idx', 'cache_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + # cache_id, not used + cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + # cache_key as created by _get_cache_key + cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # cache_args is a repo_name + cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # instance sets cache_active True when it is caching, + # other instances set cache_active to False to indicate that this cache is invalid + cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False) + + def __init__(self, cache_key, repo_name=''): + self.cache_key = cache_key + self.cache_args = repo_name + self.cache_active = False + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % (self.__class__.__name__, + self.cache_id, self.cache_key, self.cache_active) + + def _cache_key_partition(self): + prefix, repo_name, suffix = self.cache_key.partition(self.cache_args) + return prefix, repo_name, suffix + + def get_prefix(self): + """ + get prefix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[0] + + def get_suffix(self): + """ + get suffix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[2] + + @classmethod + def clear_cache(cls): + """ + Delete all cache keys from database. + Should only be run when all instances are down and all entries thus stale. + """ + cls.query().delete() + Session().commit() + + @classmethod + def _get_cache_key(cls, key): + """ + Wrapper for generating a unique cache key for this instance and "key". + key must / will start with a repo_name which will be stored in .cache_args . + """ + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') + return "%s%s" % (prefix, key) + + @classmethod + def set_invalidate(cls, repo_name, delete=False): + """ + Mark all caches of a repo as invalid in the database. + """ + inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all() + + try: + for inv_obj in inv_objs: + log.debug('marking %s key for invalidation based on repo_name=%s' + % (inv_obj, safe_str(repo_name))) + if delete: + Session().delete(inv_obj) + else: + inv_obj.cache_active = False + Session().add(inv_obj) + Session().commit() + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + + @classmethod + def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None): + """ + Mark this cache key as active and currently cached. + Return True if the existing cache registration still was valid. + Return False to indicate that it had been invalidated and caches should be refreshed. + """ + + key = (repo_name + '_' + kind) if kind else repo_name + cache_key = cls._get_cache_key(key) + + if valid_cache_keys and cache_key in valid_cache_keys: + return True + + try: + inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar() + if not inv_obj: + inv_obj = CacheInvalidation(cache_key, repo_name) + was_valid = inv_obj.cache_active + inv_obj.cache_active = True + Session().add(inv_obj) + Session().commit() + return was_valid + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + return False + + @classmethod + def get_valid_cache_keys(cls): + """ + Return opaque object with information of which caches still are valid + and can be used without checking for invalidation. + """ + return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all()) + + +class ChangesetComment(Base, BaseModel): + __tablename__ = 'changeset_comments' + __table_args__ = ( + Index('cc_revision_idx', 'revision'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + revision = Column('revision', String(40), nullable=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + line_no = Column('line_no', Unicode(10), nullable=True) + hl_lines = Column('hl_lines', Unicode(512), nullable=True) + f_path = Column('f_path', Unicode(1000), nullable=True) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) + text = Column('text', UnicodeText(25000), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan") + pull_request = relationship('PullRequest', lazy='joined') + + @classmethod + def get_users(cls, revision=None, pull_request_id=None): + """ + Returns user associated with this ChangesetComment. ie those + who actually commented + + :param cls: + :param revision: + """ + q = Session().query(User)\ + .join(ChangesetComment.author) + if revision: + q = q.filter(cls.revision == revision) + elif pull_request_id: + q = q.filter(cls.pull_request_id == pull_request_id) + return q.all() + + +class ChangesetStatus(Base, BaseModel): + __tablename__ = 'changeset_statuses' + __table_args__ = ( + Index('cs_revision_idx', 'revision'), + Index('cs_version_idx', 'version'), + UniqueConstraint('repo_id', 'revision', 'version'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed' + STATUS_APPROVED = 'approved' + STATUS_REJECTED = 'rejected' + STATUS_UNDER_REVIEW = 'under_review' + + STATUSES = [ + (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default + (STATUS_APPROVED, _("Approved")), + (STATUS_REJECTED, _("Rejected")), + (STATUS_UNDER_REVIEW, _("Under Review")), + ] + + changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + revision = Column('revision', String(40), nullable=False) + status = Column('status', String(128), nullable=False, default=DEFAULT) + changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id')) + modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now) + version = Column('version', Integer(), nullable=False, default=0) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + comment = relationship('ChangesetComment', lazy='joined') + pull_request = relationship('PullRequest', lazy='joined') + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, + self.status, self.author + ) + + @classmethod + def get_status_lbl(cls, value): + return dict(cls.STATUSES).get(value) + + @property + def status_lbl(self): + return ChangesetStatus.get_status_lbl(self.status) + + +class PullRequest(Base, BaseModel): + __tablename__ = 'pull_requests' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + # values for .status + STATUS_NEW = u'new' + STATUS_OPEN = u'open' + STATUS_CLOSED = u'closed' + + pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) + title = Column('title', Unicode(256), nullable=True) + description = Column('description', UnicodeText(10240), nullable=True) + status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW) # only for closedness, not approve/reject/etc + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max + org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + org_ref = Column('org_ref', Unicode(256), nullable=False) + other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + other_ref = Column('other_ref', Unicode(256), nullable=False) + + @hybrid_property + def revisions(self): + return self._revisions.split(':') + + @revisions.setter + def revisions(self, val): + self._revisions = ':'.join(val) + + @property + def org_ref_parts(self): + return self.org_ref.split(':') + + @property + def other_ref_parts(self): + return self.other_ref.split(':') + + author = relationship('User', lazy='joined') + reviewers = relationship('PullRequestReviewers', + cascade="all, delete, delete-orphan") + org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') + other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id') + statuses = relationship('ChangesetStatus') + comments = relationship('ChangesetComment', + cascade="all, delete, delete-orphan") + + def is_closed(self): + return self.status == self.STATUS_CLOSED + + @property + def last_review_status(self): + return self.statuses[-1].status if self.statuses else '' + + def __json__(self): + return dict( + revisions=self.revisions + ) + + +class PullRequestReviewers(Base, BaseModel): + __tablename__ = 'pull_request_reviewers' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + def __init__(self, user=None, pull_request=None): + self.user = user + self.pull_request = pull_request + + pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True) + + user = relationship('User') + pull_request = relationship('PullRequest') + + +class Notification(Base, BaseModel): + __tablename__ = 'notifications' + __table_args__ = ( + Index('notification_type_idx', 'type'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + TYPE_CHANGESET_COMMENT = u'cs_comment' + TYPE_MESSAGE = u'message' + TYPE_MENTION = u'mention' + TYPE_REGISTRATION = u'registration' + TYPE_PULL_REQUEST = u'pull_request' + TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' + + notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) + subject = Column('subject', Unicode(512), nullable=True) + body = Column('body', UnicodeText(50000), nullable=True) + created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + type_ = Column('type', Unicode(256)) + + created_by_user = relationship('User') + notifications_to_users = relationship('UserNotification', lazy='joined', + cascade="all, delete, delete-orphan") + + @property + def recipients(self): + return [x.user for x in UserNotification.query()\ + .filter(UserNotification.notification == self)\ + .order_by(UserNotification.user_id.asc()).all()] + + @classmethod + def create(cls, created_by, subject, body, recipients, type_=None): + if type_ is None: + type_ = Notification.TYPE_MESSAGE + + notification = cls() + notification.created_by_user = created_by + notification.subject = subject + notification.body = body + notification.type_ = type_ + notification.created_on = datetime.datetime.now() + + for u in recipients: + assoc = UserNotification() + assoc.notification = notification + u.notifications.append(assoc) + Session().add(notification) + return notification + + @property + def description(self): + from kallithea.model.notification import NotificationModel + return NotificationModel().make_description(self) + + +class UserNotification(Base, BaseModel): + __tablename__ = 'user_to_notification' + __table_args__ = ( + UniqueConstraint('user_id', 'notification_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True) + notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True) + read = Column('read', Boolean, default=False) + sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None) + + user = relationship('User', lazy="joined") + notification = relationship('Notification', lazy="joined", + order_by=lambda: Notification.created_on.desc(),) + + def mark_as_read(self): + self.read = True + Session().add(self) + + +class Gist(Base, BaseModel): + __tablename__ = 'gists' + __table_args__ = ( + Index('g_gist_access_id_idx', 'gist_access_id'), + Index('g_created_on_idx', 'created_on'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + GIST_PUBLIC = u'public' + GIST_PRIVATE = u'private' + + gist_id = Column('gist_id', Integer(), primary_key=True) + gist_access_id = Column('gist_access_id', Unicode(250)) + gist_description = Column('gist_description', UnicodeText(1024)) + gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True) + gist_expires = Column('gist_expires', Float(53), nullable=False) + gist_type = Column('gist_type', Unicode(128), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + owner = relationship('User') + + @classmethod + def get_or_404(cls, id_): + res = cls.query().filter(cls.gist_access_id == id_).scalar() + if not res: + raise HTTPNotFound + return res + + @classmethod + def get_by_access_id(cls, gist_access_id): + return cls.query().filter(cls.gist_access_id == gist_access_id).scalar() + + def gist_url(self): + import kallithea + alias_url = kallithea.CONFIG.get('gist_alias_url') + if alias_url: + return alias_url.replace('{gistid}', self.gist_access_id) + + from pylons import url + return url('gist', gist_id=self.gist_access_id, qualified=True) + + @classmethod + def base_path(cls): + """ + Returns base path when all gists are stored + + :param cls: + """ + from kallithea.model.gist import GIST_STORE_LOC + q = Session().query(Ui)\ + .filter(Ui.ui_key == URL_SEP) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return os.path.join(q.one().ui_value, GIST_STORE_LOC) + + def get_api_data(self): + """ + Common function for generating gist related data for API + """ + gist = self + data = dict( + gist_id=gist.gist_id, + type=gist.gist_type, + access_id=gist.gist_access_id, + description=gist.gist_description, + url=gist.gist_url(), + expires=gist.gist_expires, + created_on=gist.created_on, + ) + return data + + def __json__(self): + data = dict( + ) + data.update(self.get_api_data()) + return data + ## SCM functions + + @property + def scm_instance(self): + from kallithea.lib.vcs import get_repo + base_path = self.base_path() + return get_repo(os.path.join(*map(safe_str, + [base_path, self.gist_access_id]))) + + +class DbMigrateVersion(Base, BaseModel): + __tablename__ = 'db_migrate_version' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + repository_id = Column('repository_id', String(250), primary_key=True) + repository_path = Column('repository_path', Text) + version = Column('version', Integer) diff --git a/kallithea/lib/dbmigrate/schema/db_2_1_0.py b/kallithea/lib/dbmigrate/schema/db_2_1_0.py new file mode 100755 --- /dev/null +++ b/kallithea/lib/dbmigrate/schema/db_2_1_0.py @@ -0,0 +1,2395 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.db +~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import os +import time +import logging +import datetime +import traceback +import hashlib +import collections +import functools + +from sqlalchemy import * +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import relationship, joinedload, class_mapper, validates +from sqlalchemy.exc import DatabaseError +from beaker.cache import cache_region, region_invalidate +from webob.exc import HTTPNotFound + +from pylons.i18n.translation import lazy_ugettext as _ + +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset + +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ + safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache + +from kallithea.model.meta import Base, Session + +URL_SEP = '/' +log = logging.getLogger(__name__) + +from kallithea import DB_PREFIX + +#============================================================================== +# BASE CLASSES +#============================================================================== + +_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest() + + +class BaseModel(object): + """ + Base Model for all classess + """ + + @classmethod + def _get_keys(cls): + """return column names for this model """ + return class_mapper(cls).c.keys() + + def get_dict(self): + """ + return dict with keys and values corresponding + to this model data """ + + d = {} + for k in self._get_keys(): + d[k] = getattr(self, k) + + # also use __json__() if present to get additional fields + _json_attr = getattr(self, '__json__', None) + if _json_attr: + # update with attributes from __json__ + if callable(_json_attr): + _json_attr = _json_attr() + for k, val in _json_attr.iteritems(): + d[k] = val + return d + + def get_appstruct(self): + """return list with keys and values tupples corresponding + to this model data """ + + l = [] + for k in self._get_keys(): + l.append((k, getattr(self, k),)) + return l + + def populate_obj(self, populate_dict): + """populate model with data from given populate_dict""" + + for k in self._get_keys(): + if k in populate_dict: + setattr(self, k, populate_dict[k]) + + @classmethod + def query(cls): + return Session().query(cls) + + @classmethod + def get(cls, id_): + if id_: + return cls.query().get(id_) + + @classmethod + def get_or_404(cls, id_): + try: + id_ = int(id_) + except (TypeError, ValueError): + raise HTTPNotFound + + res = cls.query().get(id_) + if not res: + raise HTTPNotFound + return res + + @classmethod + def getAll(cls): + # deprecated and left for backward compatibility + return cls.get_all() + + @classmethod + def get_all(cls): + return cls.query().all() + + @classmethod + def delete(cls, id_): + obj = cls.query().get(id_) + Session().delete(obj) + + def __repr__(self): + if hasattr(self, '__unicode__'): + # python repr needs to return str + try: + return safe_str(self.__unicode__()) + except UnicodeDecodeError: + pass + return '' % (self.__class__.__name__) + + +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' + __table_args__ = ( + UniqueConstraint('app_settings_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + SETTINGS_TYPES = { + 'str': safe_str, + 'int': safe_int, + 'unicode': safe_unicode, + 'bool': str2bool, + 'list': functools.partial(aslist, sep=',') + } + DEFAULT_UPDATE_URL = '' + + app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + app_settings_name = Column("app_settings_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_value = Column("app_settings_value", String(4096, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _app_settings_type = Column("app_settings_type", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __init__(self, key='', val='', type='unicode'): + self.app_settings_name = key + self.app_settings_value = val + self.app_settings_type = type + + @validates('_app_settings_value') + def validate_settings_value(self, key, val): + assert type(val) == unicode + return val + + @hybrid_property + def app_settings_value(self): + v = self._app_settings_value + _type = self.app_settings_type + converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode'] + return converter(v) + + @app_settings_value.setter + def app_settings_value(self, val): + """ + Setter that will always make sure we use unicode in app_settings_value + + :param val: + """ + self._app_settings_value = safe_unicode(val) + + @hybrid_property + def app_settings_type(self): + return self._app_settings_type + + @app_settings_type.setter + def app_settings_type(self, val): + if val not in self.SETTINGS_TYPES: + raise Exception('type must be one of %s got %s' + % (self.SETTINGS_TYPES.keys(), val)) + self._app_settings_type = val + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % ( + self.__class__.__name__, + self.app_settings_name, self.app_settings_value, self.app_settings_type + ) + + @classmethod + def get_by_name(cls, key): + return cls.query()\ + .filter(cls.app_settings_name == key).scalar() + + @classmethod + def get_by_name_or_create(cls, key, val='', type='unicode'): + res = cls.get_by_name(key) + if not res: + res = cls(key, val, type) + return res + + @classmethod + def create_or_update(cls, key, val=Optional(''), type=Optional('unicode')): + """ + Creates or updates Kallithea setting. If updates is triggered it will only + update parameters that are explicityl set Optional instance will be skipped + + :param key: + :param val: + :param type: + :return: + """ + res = cls.get_by_name(key) + if not res: + val = Optional.extract(val) + type = Optional.extract(type) + res = cls(key, val, type) + else: + res.app_settings_name = key + if not isinstance(val, Optional): + # update if set + res.app_settings_value = val + if not isinstance(type, Optional): + # update if set + res.app_settings_type = type + return res + + @classmethod + def get_app_settings(cls, cache=False): + + ret = cls.query() + + if cache: + ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) + + if not ret: + raise Exception('Could not get application settings !') + settings = {} + for each in ret: + settings[each.app_settings_name] = \ + each.app_settings_value + + return settings + + @classmethod + def get_auth_plugins(cls, cache=False): + auth_plugins = cls.get_by_name("auth_plugins").app_settings_value + return auth_plugins + + @classmethod + def get_auth_settings(cls, cache=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('auth_')).all() + fd = {} + for row in ret: + fd.update({row.app_settings_name: row.app_settings_value}) + + return fd + + @classmethod + def get_default_repo_settings(cls, cache=False, strip_prefix=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('default_')).all() + fd = {} + for row in ret: + key = row.app_settings_name + if strip_prefix: + key = remove_prefix(key, prefix='default_') + fd.update({key: row.app_settings_value}) + + return fd + + @classmethod + def get_server_info(cls): + import pkg_resources + import platform + import kallithea + from kallithea.lib.utils import check_git_version + mods = [(p.project_name, p.version) for p in pkg_resources.working_set] + info = { + 'modules': sorted(mods, key=lambda k: k[0].lower()), + 'py_version': platform.python_version(), + 'platform': safe_unicode(platform.platform()), + 'kallithea_version': kallithea.__version__, + 'git_version': safe_unicode(check_git_version()), + 'git_path': kallithea.CONFIG.get('git_path') + } + return info + + +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' + __table_args__ = ( + UniqueConstraint('ui_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + HOOK_UPDATE = 'changegroup.update' + HOOK_REPO_SIZE = 'changegroup.repo_size' + HOOK_PUSH = 'changegroup.push_logger' + HOOK_PRE_PUSH = 'prechangegroup.pre_push' + HOOK_PULL = 'outgoing.pull_logger' + HOOK_PRE_PULL = 'preoutgoing.pre_pull' + + ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) + + # def __init__(self, section='', key='', value=''): + # self.ui_section = section + # self.ui_key = key + # self.ui_value = value + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.ui_key == key).scalar() + + @classmethod + def get_builtin_hooks(cls): + q = cls.query() + q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + return q.all() + + @classmethod + def get_custom_hooks(cls): + q = cls.query() + q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + q = q.filter(cls.ui_section == 'hooks') + return q.all() + + @classmethod + def get_repos_location(cls): + return cls.get_by_key('/').ui_value + + @classmethod + def create_or_update_hook(cls, key, val): + new_ui = cls.get_by_key(key) or cls() + new_ui.ui_section = 'hooks' + new_ui.ui_active = True + new_ui.ui_key = key + new_ui.ui_value = val + + Session().add(new_ui) + + def __repr__(self): + return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section, + self.ui_key, self.ui_value) + + +class User(Base, BaseModel): + __tablename__ = 'users' + __table_args__ = ( + UniqueConstraint('username'), UniqueConstraint('email'), + Index('u_username_idx', 'username'), + Index('u_email_idx', 'email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + DEFAULT_USER = 'default' + DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}' + + user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + admin = Column("admin", Boolean(), nullable=True, unique=None, default=False) + name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) + extern_type = Column("extern_type", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + extern_name = Column("extern_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + user_log = relationship('UserLog') + user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') + + repositories = relationship('Repository') + user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all') + followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all') + + repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all') + repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all') + + group_member = relationship('UserGroupMember', cascade='all') + + notifications = relationship('UserNotification', cascade='all') + # notifications assigned to this user + user_created_notifications = relationship('Notification', cascade='all') + # comments created by this user + user_comments = relationship('ChangesetComment', cascade='all') + #extra emails for this user + user_emails = relationship('UserEmailMap', cascade='all') + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + @property + def firstname(self): + # alias for future + return self.name + + @property + def emails(self): + other = UserEmailMap.query().filter(UserEmailMap.user==self).all() + return [self.email] + [x.email for x in other] + + @property + def ip_addresses(self): + ret = UserIpMap.query().filter(UserIpMap.user == self).all() + return [x.ip_addr for x in ret] + + @property + def username_and_name(self): + return '%s (%s %s)' % (self.username, self.firstname, self.lastname) + + @property + def full_name(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def full_name_or_username(self): + return ('%s %s' % (self.firstname, self.lastname) + if (self.firstname and self.lastname) else self.username) + + @property + def full_contact(self): + return '%s %s <%s>' % (self.firstname, self.lastname, self.email) + + @property + def short_contact(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def is_admin(self): + return self.admin + + @property + def AuthUser(self): + """ + Returns instance of AuthUser for this user + """ + from kallithea.lib.auth import AuthUser + return AuthUser(user_id=self.user_id, api_key=self.api_key, + username=self.username) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.user_id, self.username) + + @classmethod + def get_by_username(cls, username, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.username.ilike(username)) + else: + q = cls.query().filter(cls.username == username) + + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(username) + ) + ) + return q.scalar() + + @classmethod + def get_by_api_key(cls, api_key, cache=False, fallback=True): + q = cls.query().filter(cls.api_key == api_key) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_api_key_%s" % api_key)) + res = q.scalar() + + if fallback and not res: + #fallback to additional keys + _res = UserApiKeys.query()\ + .filter(UserApiKeys.api_key == api_key)\ + .filter(or_(UserApiKeys.expires == -1, + UserApiKeys.expires >= time.time()))\ + .first() + if _res: + res = _res.user + return res + + @classmethod + def get_by_email(cls, email, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.email.ilike(email)) + else: + q = cls.query().filter(cls.email == email) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_key_%s" % email)) + + ret = q.scalar() + if ret is None: + q = UserEmailMap.query() + # try fetching in alternate email map + if case_insensitive: + q = q.filter(UserEmailMap.email.ilike(email)) + else: + q = q.filter(UserEmailMap.email == email) + q = q.options(joinedload(UserEmailMap.user)) + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_map_key_%s" % email)) + ret = getattr(q.scalar(), 'user', None) + + return ret + + @classmethod + def get_from_cs_author(cls, author): + """ + Tries to get User objects out of commit author string + + :param author: + """ + from kallithea.lib.helpers import email, author_name + # Valid email in the attribute passed, see if they're in the system + _email = email(author) + if _email: + user = cls.get_by_email(_email, case_insensitive=True) + if user: + return user + # Maybe we can match by username? + _author = author_name(author) + user = cls.get_by_username(_author, case_insensitive=True) + if user: + return user + + def update_lastlogin(self): + """Update user lastlogin""" + self.last_login = datetime.datetime.now() + Session().add(self) + log.debug('updated user %s lastlogin' % self.username) + + @classmethod + def get_first_admin(cls): + user = User.query().filter(User.admin == True).first() + if user is None: + raise Exception('Missing administrative account!') + return user + + @classmethod + def get_default_user(cls, cache=False): + user = User.get_by_username(User.DEFAULT_USER, cache=cache) + if user is None: + raise Exception('Missing default account!') + return user + + def get_api_data(self): + """ + Common function for generating user related data for API + """ + user = self + data = dict( + user_id=user.user_id, + username=user.username, + firstname=user.name, + lastname=user.lastname, + email=user.email, + emails=user.emails, + api_key=user.api_key, + active=user.active, + admin=user.admin, + extern_type=user.extern_type, + extern_name=user.extern_name, + last_login=user.last_login, + ip_addresses=user.ip_addresses + ) + return data + + def __json__(self): + data = dict( + full_name=self.full_name, + full_name_or_username=self.full_name_or_username, + short_contact=self.short_contact, + full_contact=self.full_contact + ) + data.update(self.get_api_data()) + return data + + +class UserApiKeys(Base, BaseModel): + __tablename__ = 'user_api_keys' + __table_args__ = ( + Index('uak_api_key_idx', 'api_key'), + UniqueConstraint('api_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True) + description = Column('description', UnicodeText(1024)) + expires = Column('expires', Float(53), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + user = relationship('User', lazy='joined') + + +class UserEmailMap(Base, BaseModel): + __tablename__ = 'user_email_map' + __table_args__ = ( + Index('uem_email_idx', 'email'), + UniqueConstraint('email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + user = relationship('User', lazy='joined') + + @validates('_email') + def validate_email(self, key, email): + # check if this email is not main one + main_email = Session().query(User).filter(User.email == email).scalar() + if main_email is not None: + raise AttributeError('email %s is present is user table' % email) + return email + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + +class UserIpMap(Base, BaseModel): + __tablename__ = 'user_ip_map' + __table_args__ = ( + UniqueConstraint('user_id', 'ip_addr'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + user = relationship('User', lazy='joined') + + @classmethod + def _get_ip_range(cls, ip_addr): + from kallithea.lib import ipaddr + net = ipaddr.IPNetwork(address=ip_addr) + return [str(net.network), str(net.broadcast)] + + def __json__(self): + return dict( + ip_addr=self.ip_addr, + ip_range=self._get_ip_range(self.ip_addr) + ) + + def __unicode__(self): + return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__, + self.user_id, self.ip_addr) + +class UserLog(Base, BaseModel): + __tablename__ = 'user_logs' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True) + repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.repository_name, + self.action) + + @property + def action_as_day(self): + return datetime.date(*self.action_date.timetuple()[:3]) + + user = relationship('User') + repository = relationship('Repository', cascade='') + + +class UserGroup(Base, BaseModel): + __tablename__ = 'users_groups' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + user_group_description = Column("user_group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined") + users_group_to_perm = relationship('UserGroupToPerm', cascade='all') + users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all') + user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all') + + user = relationship('User') + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.users_group_id, + self.users_group_name) + + @classmethod + def get_by_group_name(cls, group_name, cache=False, + case_insensitive=False): + if case_insensitive: + q = cls.query().filter(cls.users_group_name.ilike(group_name)) + else: + q = cls.query().filter(cls.users_group_name == group_name) + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(group_name) + ) + ) + return q.scalar() + + @classmethod + def get(cls, user_group_id, cache=False): + user_group = cls.query() + if cache: + user_group = user_group.options(FromCache("sql_cache_short", + "get_users_group_%s" % user_group_id)) + return user_group.get(user_group_id) + + def get_api_data(self, with_members=True): + user_group = self + + data = dict( + users_group_id=user_group.users_group_id, + group_name=user_group.users_group_name, + group_description=user_group.user_group_description, + active=user_group.users_group_active, + owner=user_group.user.username, + ) + if with_members: + members = [] + for user in user_group.members: + user = user.user + members.append(user.get_api_data()) + data['members'] = members + + return data + + +class UserGroupMember(Base, BaseModel): + __tablename__ = 'users_groups_members' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + + user = relationship('User', lazy='joined') + users_group = relationship('UserGroup') + + def __init__(self, gr_id='', u_id=''): + self.users_group_id = gr_id + self.user_id = u_id + + +class RepositoryField(Base, BaseModel): + __tablename__ = 'repositories_fields' + __table_args__ = ( + UniqueConstraint('repository_id', 'field_key'), # no-multi field + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields + + repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + field_key = Column("field_key", String(250, convert_unicode=False, assert_unicode=None)) + field_label = Column("field_label", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_value = Column("field_value", String(10000, convert_unicode=False, assert_unicode=None), nullable=False) + field_desc = Column("field_desc", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_type = Column("field_type", String(256), nullable=False, unique=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repository = relationship('Repository') + + @property + def field_key_prefixed(self): + return 'ex_%s' % self.field_key + + @classmethod + def un_prefix_key(cls, key): + if key.startswith(cls.PREFIX): + return key[len(cls.PREFIX):] + return key + + @classmethod + def get_by_key_name(cls, key, repo): + row = cls.query()\ + .filter(cls.repository == repo)\ + .filter(cls.field_key == key).scalar() + return row + + +class Repository(Base, BaseModel): + __tablename__ = 'repositories' + __table_args__ = ( + UniqueConstraint('repo_name'), + Index('r_repo_name_idx', 'repo_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}' + + repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + private = Column("private", Boolean(), nullable=True, unique=None, default=None) + enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True) + enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True) + description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + _landing_revision = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data + + fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) + + user = relationship('User') + fork = relationship('Repository', remote_side=repo_id) + group = relationship('RepoGroup') + repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + stats = relationship('Statistics', cascade='all', uselist=False) + + followers = relationship('UserFollowing', + primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', + cascade='all') + extra_fields = relationship('RepositoryField', + cascade="all, delete, delete-orphan") + + logs = relationship('UserLog') + comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan") + + pull_requests_org = relationship('PullRequest', + primaryjoin='PullRequest.org_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + pull_requests_other = relationship('PullRequest', + primaryjoin='PullRequest.other_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, + safe_unicode(self.repo_name)) + + @hybrid_property + def landing_rev(self): + # always should return [rev_type, rev] + if self._landing_revision: + _rev_info = self._landing_revision.split(':') + if len(_rev_info) < 2: + _rev_info.insert(0, 'rev') + return [_rev_info[0], _rev_info[1]] + return [None, None] + + @landing_rev.setter + def landing_rev(self, val): + if ':' not in val: + raise ValueError('value must be delimited with `:` and consist ' + 'of :, got %s instead' % val) + self._landing_revision = val + + @hybrid_property + def locked(self): + # always should return [user_id, timelocked] + if self._locked: + _lock_info = self._locked.split(':') + return int(_lock_info[0]), _lock_info[1] + return [None, None] + + @locked.setter + def locked(self, val): + if val and isinstance(val, (list, tuple)): + self._locked = ':'.join(map(str, val)) + else: + self._locked = None + + @hybrid_property + def changeset_cache(self): + from kallithea.lib.vcs.backends.base import EmptyChangeset + dummy = EmptyChangeset().__json__() + if not self._changeset_cache: + return dummy + try: + return json.loads(self._changeset_cache) + except TypeError: + return dummy + + @changeset_cache.setter + def changeset_cache(self, val): + try: + self._changeset_cache = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def normalize_repo_name(cls, repo_name): + """ + Normalizes os specific repo_name to the format internally stored inside + dabatabase using URL_SEP + + :param cls: + :param repo_name: + """ + return cls.url_sep().join(repo_name.split(os.sep)) + + @classmethod + def get_by_repo_name(cls, repo_name): + q = Session().query(cls).filter(cls.repo_name == repo_name) + q = q.options(joinedload(Repository.fork))\ + .options(joinedload(Repository.user))\ + .options(joinedload(Repository.group)) + return q.scalar() + + @classmethod + def get_by_full_path(cls, repo_full_path): + repo_name = repo_full_path.split(cls.base_path(), 1)[-1] + repo_name = cls.normalize_repo_name(repo_name) + return cls.get_by_repo_name(repo_name.strip(URL_SEP)) + + @classmethod + def get_repo_forks(cls, repo_id): + return cls.query().filter(Repository.fork_id == repo_id) + + @classmethod + def base_path(cls): + """ + Returns base path when all repos are stored + + :param cls: + """ + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def forks(self): + """ + Return forks of this repo + """ + return Repository.get_repo_forks(self.repo_id) + + @property + def parent(self): + """ + Returns fork parent + """ + return self.fork + + @property + def just_name(self): + return self.repo_name.split(Repository.url_sep())[-1] + + @property + def groups_with_parents(self): + groups = [] + if self.group is None: + return groups + + cur_gr = self.group + groups.insert(0, cur_gr) + while 1: + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + groups.insert(0, gr) + + return groups + + @property + def groups_and_repo(self): + return self.groups_with_parents, self.just_name, self.repo_name + + @LazyProperty + def repo_path(self): + """ + Returns base full path for that repository means where it actually + exists on a filesystem + """ + q = Session().query(Ui).filter(Ui.ui_key == + Repository.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def repo_full_path(self): + p = [self.repo_path] + # we need to split the name by / since this is how we store the + # names in the database, but that eventually needs to be converted + # into a valid system path + p += self.repo_name.split(Repository.url_sep()) + return os.path.join(*map(safe_unicode, p)) + + @property + def cache_keys(self): + """ + Returns associated cache keys for that repo + """ + return CacheInvalidation.query()\ + .filter(CacheInvalidation.cache_args == self.repo_name)\ + .order_by(CacheInvalidation.cache_key)\ + .all() + + def get_new_name(self, repo_name): + """ + returns new full repository name based on assigned group and new new + + :param group_name: + """ + path_prefix = self.group.full_path_splitted if self.group else [] + return Repository.url_sep().join(path_prefix + [repo_name]) + + @property + def _ui(self): + """ + Creates an db based ui object for this repository + """ + from kallithea.lib.utils import make_ui + return make_ui('db', clear_session=False) + + @classmethod + def is_valid(cls, repo_name): + """ + returns True if given repo name is a valid filesystem repository + + :param cls: + :param repo_name: + """ + from kallithea.lib.utils import is_valid_repo + + return is_valid_repo(repo_name, cls.base_path()) + + def get_api_data(self): + """ + Common function for generating repo api data + + """ + repo = self + data = dict( + repo_id=repo.repo_id, + repo_name=repo.repo_name, + repo_type=repo.repo_type, + clone_uri=repo.clone_uri, + private=repo.private, + created_on=repo.created_on, + description=repo.description, + landing_rev=repo.landing_rev, + owner=repo.user.username, + fork_of=repo.fork.repo_name if repo.fork else None, + enable_statistics=repo.enable_statistics, + enable_locking=repo.enable_locking, + enable_downloads=repo.enable_downloads, + last_changeset=repo.changeset_cache, + locked_by=User.get(self.locked[0]).get_api_data() \ + if self.locked[0] else None, + locked_date=time_to_datetime(self.locked[1]) \ + if self.locked[1] else None + ) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) + if repository_fields: + for f in self.extra_fields: + data[f.field_key_prefixed] = f.field_value + + return data + + @classmethod + def lock(cls, repo, user_id, lock_time=None): + if not lock_time: + lock_time = time.time() + repo.locked = [user_id, lock_time] + Session().add(repo) + Session().commit() + + @classmethod + def unlock(cls, repo): + repo.locked = None + Session().add(repo) + Session().commit() + + @classmethod + def getlock(cls, repo): + return repo.locked + + @property + def last_db_change(self): + return self.updated_on + + def clone_url(self, **override): + from pylons import url + from urlparse import urlparse + import urllib + parsed_url = urlparse(url('home', qualified=True)) + default_clone_uri = '%(scheme)s://%(user)s%(pass)s%(netloc)s%(prefix)s%(path)s' + decoded_path = safe_unicode(urllib.unquote(parsed_url.path)) + args = { + 'user': '', + 'pass': '', + 'scheme': parsed_url.scheme, + 'netloc': parsed_url.netloc, + 'prefix': decoded_path, + 'path': self.repo_name + } + + args.update(override) + return default_clone_uri % args + + #========================================================================== + # SCM PROPERTIES + #========================================================================== + + def get_changeset(self, rev=None): + return get_changeset_safe(self.scm_instance, rev) + + def get_landing_changeset(self): + """ + Returns landing changeset, or if that doesn't exist returns the tip + """ + _rev_type, _rev = self.landing_rev + cs = self.get_changeset(_rev) + if isinstance(cs, EmptyChangeset): + return self.get_changeset() + return cs + + def update_changeset_cache(self, cs_cache=None): + """ + Update cache of last changeset for repository, keys should be:: + + short_id + raw_id + revision + message + date + author + + :param cs_cache: + """ + from kallithea.lib.vcs.backends.base import BaseChangeset + if cs_cache is None: + cs_cache = EmptyChangeset() + # use no-cache version here + scm_repo = self.scm_instance_no_cache() + if scm_repo: + cs_cache = scm_repo.get_changeset() + + if isinstance(cs_cache, BaseChangeset): + cs_cache = cs_cache.__json__() + + if (cs_cache != self.changeset_cache or not self.changeset_cache): + _default = datetime.datetime.fromtimestamp(0) + last_change = cs_cache.get('date') or _default + log.debug('updated repo %s with new cs cache %s' + % (self.repo_name, cs_cache)) + self.updated_on = last_change + self.changeset_cache = cs_cache + Session().add(self) + Session().commit() + else: + log.debug('Skipping repo:%s already with latest changes' + % self.repo_name) + + @property + def tip(self): + return self.get_changeset('tip') + + @property + def author(self): + return self.tip.author + + @property + def last_change(self): + return self.scm_instance.last_change + + def get_comments(self, revisions=None): + """ + Returns comments for this repository grouped by revisions + + :param revisions: filter query by revisions only + """ + cmts = ChangesetComment.query()\ + .filter(ChangesetComment.repo == self) + if revisions: + cmts = cmts.filter(ChangesetComment.revision.in_(revisions)) + grouped = collections.defaultdict(list) + for cmt in cmts.all(): + grouped[cmt.revision].append(cmt) + return grouped + + def statuses(self, revisions=None): + """ + Returns statuses for this repository + + :param revisions: list of revisions to get statuses for + """ + + statuses = ChangesetStatus.query()\ + .filter(ChangesetStatus.repo == self)\ + .filter(ChangesetStatus.version == 0) + if revisions: + statuses = statuses.filter(ChangesetStatus.revision.in_(revisions)) + grouped = {} + + #maybe we have open new pullrequest without a status ? + stat = ChangesetStatus.STATUS_UNDER_REVIEW + status_lbl = ChangesetStatus.get_status_lbl(stat) + for pr in PullRequest.query().filter(PullRequest.org_repo == self).all(): + for rev in pr.revisions: + pr_id = pr.pull_request_id + pr_repo = pr.other_repo.repo_name + grouped[rev] = [stat, status_lbl, pr_id, pr_repo] + + for stat in statuses.all(): + pr_id = pr_repo = None + if stat.pull_request: + pr_id = stat.pull_request.pull_request_id + pr_repo = stat.pull_request.other_repo.repo_name + grouped[stat.revision] = [str(stat.status), stat.status_lbl, + pr_id, pr_repo] + return grouped + + def _repo_size(self): + from kallithea.lib import helpers as h + log.debug('calculating repository size...') + return h.format_byte_size(self.scm_instance.size) + + #========================================================================== + # SCM CACHE INSTANCE + #========================================================================== + + def set_invalidate(self): + """ + Mark caches of this repo as invalid. + """ + CacheInvalidation.set_invalidate(self.repo_name) + + def scm_instance_no_cache(self): + return self.__get_instance() + + @property + def scm_instance(self): + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) + if full_cache: + return self.scm_instance_cached() + return self.__get_instance() + + def scm_instance_cached(self, valid_cache_keys=None): + @cache_region('long_term') + def _c(repo_name): + return self.__get_instance() + rn = self.repo_name + + valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys) + if not valid: + log.debug('Cache for %s invalidated, getting new object' % (rn)) + region_invalidate(_c, None, rn) + else: + log.debug('Getting obj for %s from cache' % (rn)) + return _c(rn) + + def __get_instance(self): + repo_full_path = self.repo_full_path + try: + alias = get_scm(repo_full_path)[0] + log.debug('Creating instance of %s repository from %s' + % (alias, repo_full_path)) + backend = get_backend(alias) + except VCSError: + log.error(traceback.format_exc()) + log.error('Perhaps this repository is in db and not in ' + 'filesystem run rescan repositories with ' + '"destroy old data " option from admin panel') + return + + if alias == 'hg': + + repo = backend(safe_str(repo_full_path), create=False, + baseui=self._ui) + # skip hidden web repository + if repo._get_hidden(): + return + else: + repo = backend(repo_full_path, create=False) + + return repo + + def __json__(self): + return dict(landing_rev = self.landing_rev) + +class RepoGroup(Base, BaseModel): + __tablename__ = 'groups' + __table_args__ = ( + UniqueConstraint('group_name', 'group_parent_id'), + CheckConstraint('group_id != group_parent_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + __mapper_args__ = {'order_by': 'group_name'} + + group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + group_name = Column("group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) + group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + parent_group = relationship('RepoGroup', remote_side=group_id) + user = relationship('User') + + def __init__(self, group_name='', parent_group=None): + self.group_name = group_name + self.parent_group = parent_group + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id, + self.group_name) + + @classmethod + def groups_choices(cls, groups=None, show_empty_group=True): + from webhelpers.html import literal as _literal + if not groups: + groups = cls.query().all() + + repo_groups = [] + if show_empty_group: + repo_groups = [('-1', u'-- %s --' % _('top level'))] + sep = ' » ' + _name = lambda k: _literal(sep.join(k)) + + repo_groups.extend([(x.group_id, _name(x.full_path_splitted)) + for x in groups]) + + repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0]) + return repo_groups + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): + if case_insensitive: + gr = cls.query()\ + .filter(cls.group_name.ilike(group_name)) + else: + gr = cls.query()\ + .filter(cls.group_name == group_name) + if cache: + gr = gr.options(FromCache( + "sql_cache_short", + "get_group_%s" % _hash_key(group_name) + ) + ) + return gr.scalar() + + @property + def parents(self): + parents_recursion_limit = 5 + groups = [] + if self.parent_group is None: + return groups + cur_gr = self.parent_group + groups.insert(0, cur_gr) + cnt = 0 + while 1: + cnt += 1 + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + if cnt == parents_recursion_limit: + # this will prevent accidental infinit loops + log.error('group nested more than %s' % + parents_recursion_limit) + break + + groups.insert(0, gr) + return groups + + @property + def children(self): + return RepoGroup.query().filter(RepoGroup.parent_group == self) + + @property + def name(self): + return self.group_name.split(RepoGroup.url_sep())[-1] + + @property + def full_path(self): + return self.group_name + + @property + def full_path_splitted(self): + return self.group_name.split(RepoGroup.url_sep()) + + @property + def repositories(self): + return Repository.query()\ + .filter(Repository.group == self)\ + .order_by(Repository.repo_name) + + @property + def repositories_recursive_count(self): + cnt = self.repositories.count() + + def children_count(group): + cnt = 0 + for child in group.children: + cnt += child.repositories.count() + cnt += children_count(child) + return cnt + + return cnt + children_count(self) + + def _recursive_objects(self, include_repos=True): + all_ = [] + + def _get_members(root_gr): + if include_repos: + for r in root_gr.repositories: + all_.append(r) + childs = root_gr.children.all() + if childs: + for gr in childs: + all_.append(gr) + _get_members(gr) + + _get_members(self) + return [self] + all_ + + def recursive_groups_and_repos(self): + """ + Recursive return all groups, with repositories in those groups + """ + return self._recursive_objects() + + def recursive_groups(self): + """ + Returns all children groups for this group including children of children + """ + return self._recursive_objects(include_repos=False) + + def get_new_name(self, group_name): + """ + returns new full group name based on parent and new name + + :param group_name: + """ + path_prefix = (self.parent_group.full_path_splitted if + self.parent_group else []) + return RepoGroup.url_sep().join(path_prefix + [group_name]) + + def get_api_data(self): + """ + Common function for generating api data + + """ + group = self + data = dict( + group_id=group.group_id, + group_name=group.group_name, + group_description=group.group_description, + parent_group=group.parent_group.group_name if group.parent_group else None, + repositories=[x.repo_name for x in group.repositories], + owner=group.user.username + ) + return data + + +class Permission(Base, BaseModel): + __tablename__ = 'permissions' + __table_args__ = ( + Index('p_perm_name_idx', 'permission_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PERMS = [ + ('hg.admin', _('Kallithea Administrator')), + + ('repository.none', _('Repository no access')), + ('repository.read', _('Repository read access')), + ('repository.write', _('Repository write access')), + ('repository.admin', _('Repository admin access')), + + ('group.none', _('Repository group no access')), + ('group.read', _('Repository group read access')), + ('group.write', _('Repository group write access')), + ('group.admin', _('Repository group admin access')), + + ('usergroup.none', _('User group no access')), + ('usergroup.read', _('User group read access')), + ('usergroup.write', _('User group write access')), + ('usergroup.admin', _('User group admin access')), + + ('hg.repogroup.create.false', _('Repository Group creation disabled')), + ('hg.repogroup.create.true', _('Repository Group creation enabled')), + + ('hg.usergroup.create.false', _('User Group creation disabled')), + ('hg.usergroup.create.true', _('User Group creation enabled')), + + ('hg.create.none', _('Repository creation disabled')), + ('hg.create.repository', _('Repository creation enabled')), + + ('hg.fork.none', _('Repository forking disabled')), + ('hg.fork.repository', _('Repository forking enabled')), + + ('hg.register.none', _('Registration disabled')), + ('hg.register.manual_activate', _('User Registration with manual account activation')), + ('hg.register.auto_activate', _('User Registration with automatic account activation')), + + ('hg.extern_activate.manual', _('Manual activation of external account')), + ('hg.extern_activate.auto', _('Automatic activation of external account')), + + ] + + #definition of system default permissions for DEFAULT user + DEFAULT_USER_PERMISSIONS = [ + 'repository.read', + 'group.read', + 'usergroup.read', + 'hg.create.repository', + 'hg.fork.repository', + 'hg.register.manual_activate', + 'hg.extern_activate.auto', + ] + + # defines which permissions are more important higher the more important + # Weight defines which permissions are more important. + # The higher number the more important. + PERM_WEIGHTS = { + 'repository.none': 0, + 'repository.read': 1, + 'repository.write': 3, + 'repository.admin': 4, + + 'group.none': 0, + 'group.read': 1, + 'group.write': 3, + 'group.admin': 4, + + 'usergroup.none': 0, + 'usergroup.read': 1, + 'usergroup.write': 3, + 'usergroup.admin': 4, + 'hg.repogroup.create.false': 0, + 'hg.repogroup.create.true': 1, + + 'hg.usergroup.create.false': 0, + 'hg.usergroup.create.true': 1, + + 'hg.fork.none': 0, + 'hg.fork.repository': 1, + 'hg.create.none': 0, + 'hg.create.repository': 1 + } + + permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, self.permission_id, self.permission_name + ) + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.permission_name == key).scalar() + + @classmethod + def get_default_perms(cls, default_user_id): + q = Session().query(UserRepoToPerm, Repository, cls)\ + .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ + .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_group_perms(cls, default_user_id): + q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\ + .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\ + .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoGroupToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_user_group_perms(cls, default_user_id): + q = Session().query(UserUserGroupToPerm, UserGroup, cls)\ + .join((UserGroup, UserUserGroupToPerm.user_group_id == UserGroup.users_group_id))\ + .join((cls, UserUserGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserUserGroupToPerm.user_id == default_user_id) + + return q.all() + + +class UserRepoToPerm(Base, BaseModel): + __tablename__ = 'repo_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'repository_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + repository = relationship('Repository') + permission = relationship('Permission') + + @classmethod + def create(cls, user, repository, permission): + n = cls() + n.user = user + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.repository) + + +class UserUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'user_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + user_group = relationship('UserGroup') + permission = relationship('Permission') + + @classmethod + def create(cls, user, user_group, permission): + n = cls() + n.user = user + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.user_group) + + +class UserToPerm(Base, BaseModel): + __tablename__ = 'user_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + permission = relationship('Permission', lazy='joined') + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.permission) + + +class UserGroupRepoToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_to_perm' + __table_args__ = ( + UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + repository = relationship('Repository') + + @classmethod + def create(cls, users_group, repository, permission): + n = cls() + n.users_group = users_group + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.users_group, self.repository) + + +class UserGroupUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_group_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'), + CheckConstraint('target_user_group_id != user_group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id') + user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id') + permission = relationship('Permission') + + @classmethod + def create(cls, target_user_group, user_group, permission): + n = cls() + n.target_user_group = target_user_group + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.target_user_group, self.user_group) + + +class UserGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'permission_id',), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + + +class UserRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'user_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + group = relationship('RepoGroup') + permission = relationship('Permission') + + +class UserGroupRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + group = relationship('RepoGroup') + + +class Statistics(Base, BaseModel): + __tablename__ = 'statistics' + __table_args__ = ( + UniqueConstraint('repository_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) + stat_on_revision = Column("stat_on_revision", Integer(), nullable=False) + commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data + commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data + languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data + + repository = relationship('Repository', single_parent=True) + + +class UserFollowing(Base, BaseModel): + __tablename__ = 'user_followings' + __table_args__ = ( + UniqueConstraint('user_id', 'follows_repository_id'), + UniqueConstraint('user_id', 'follows_user_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None) + follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + + user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') + + follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') + follows_repository = relationship('Repository', order_by='Repository.repo_name') + + @classmethod + def get_repo_followers(cls, repo_id): + return cls.query().filter(cls.follows_repo_id == repo_id) + + +class CacheInvalidation(Base, BaseModel): + __tablename__ = 'cache_invalidation' + __table_args__ = ( + UniqueConstraint('cache_key'), + Index('key_idx', 'cache_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + # cache_id, not used + cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + # cache_key as created by _get_cache_key + cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # cache_args is a repo_name + cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + # instance sets cache_active True when it is caching, + # other instances set cache_active to False to indicate that this cache is invalid + cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False) + + def __init__(self, cache_key, repo_name=''): + self.cache_key = cache_key + self.cache_args = repo_name + self.cache_active = False + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % (self.__class__.__name__, + self.cache_id, self.cache_key, self.cache_active) + + def _cache_key_partition(self): + prefix, repo_name, suffix = self.cache_key.partition(self.cache_args) + return prefix, repo_name, suffix + + def get_prefix(self): + """ + get prefix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[0] + + def get_suffix(self): + """ + get suffix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[2] + + @classmethod + def clear_cache(cls): + """ + Delete all cache keys from database. + Should only be run when all instances are down and all entries thus stale. + """ + cls.query().delete() + Session().commit() + + @classmethod + def _get_cache_key(cls, key): + """ + Wrapper for generating a unique cache key for this instance and "key". + key must / will start with a repo_name which will be stored in .cache_args . + """ + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') + return "%s%s" % (prefix, key) + + @classmethod + def set_invalidate(cls, repo_name, delete=False): + """ + Mark all caches of a repo as invalid in the database. + """ + inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all() + + try: + for inv_obj in inv_objs: + log.debug('marking %s key for invalidation based on repo_name=%s' + % (inv_obj, safe_str(repo_name))) + if delete: + Session().delete(inv_obj) + else: + inv_obj.cache_active = False + Session().add(inv_obj) + Session().commit() + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + + @classmethod + def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None): + """ + Mark this cache key as active and currently cached. + Return True if the existing cache registration still was valid. + Return False to indicate that it had been invalidated and caches should be refreshed. + """ + + key = (repo_name + '_' + kind) if kind else repo_name + cache_key = cls._get_cache_key(key) + + if valid_cache_keys and cache_key in valid_cache_keys: + return True + + try: + inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar() + if not inv_obj: + inv_obj = CacheInvalidation(cache_key, repo_name) + was_valid = inv_obj.cache_active + inv_obj.cache_active = True + Session().add(inv_obj) + Session().commit() + return was_valid + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + return False + + @classmethod + def get_valid_cache_keys(cls): + """ + Return opaque object with information of which caches still are valid + and can be used without checking for invalidation. + """ + return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all()) + + +class ChangesetComment(Base, BaseModel): + __tablename__ = 'changeset_comments' + __table_args__ = ( + Index('cc_revision_idx', 'revision'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + revision = Column('revision', String(40), nullable=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + line_no = Column('line_no', Unicode(10), nullable=True) + hl_lines = Column('hl_lines', Unicode(512), nullable=True) + f_path = Column('f_path', Unicode(1000), nullable=True) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) + text = Column('text', UnicodeText(25000), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan") + pull_request = relationship('PullRequest', lazy='joined') + + @classmethod + def get_users(cls, revision=None, pull_request_id=None): + """ + Returns user associated with this ChangesetComment. ie those + who actually commented + + :param cls: + :param revision: + """ + q = Session().query(User)\ + .join(ChangesetComment.author) + if revision: + q = q.filter(cls.revision == revision) + elif pull_request_id: + q = q.filter(cls.pull_request_id == pull_request_id) + return q.all() + + +class ChangesetStatus(Base, BaseModel): + __tablename__ = 'changeset_statuses' + __table_args__ = ( + Index('cs_revision_idx', 'revision'), + Index('cs_version_idx', 'version'), + UniqueConstraint('repo_id', 'revision', 'version'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed' + STATUS_APPROVED = 'approved' + STATUS_REJECTED = 'rejected' + STATUS_UNDER_REVIEW = 'under_review' + + STATUSES = [ + (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default + (STATUS_APPROVED, _("Approved")), + (STATUS_REJECTED, _("Rejected")), + (STATUS_UNDER_REVIEW, _("Under Review")), + ] + + changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + revision = Column('revision', String(40), nullable=False) + status = Column('status', String(128), nullable=False, default=DEFAULT) + changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id')) + modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now) + version = Column('version', Integer(), nullable=False, default=0) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + comment = relationship('ChangesetComment', lazy='joined') + pull_request = relationship('PullRequest', lazy='joined') + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, + self.status, self.author + ) + + @classmethod + def get_status_lbl(cls, value): + return dict(cls.STATUSES).get(value) + + @property + def status_lbl(self): + return ChangesetStatus.get_status_lbl(self.status) + + +class PullRequest(Base, BaseModel): + __tablename__ = 'pull_requests' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + # values for .status + STATUS_NEW = u'new' + STATUS_OPEN = u'open' + STATUS_CLOSED = u'closed' + + pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) + title = Column('title', Unicode(256), nullable=True) + description = Column('description', UnicodeText(10240), nullable=True) + status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW) # only for closedness, not approve/reject/etc + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max + org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + org_ref = Column('org_ref', Unicode(256), nullable=False) + other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + other_ref = Column('other_ref', Unicode(256), nullable=False) + + @hybrid_property + def revisions(self): + return self._revisions.split(':') + + @revisions.setter + def revisions(self, val): + self._revisions = ':'.join(val) + + @property + def org_ref_parts(self): + return self.org_ref.split(':') + + @property + def other_ref_parts(self): + return self.other_ref.split(':') + + author = relationship('User', lazy='joined') + reviewers = relationship('PullRequestReviewers', + cascade="all, delete, delete-orphan") + org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') + other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id') + statuses = relationship('ChangesetStatus') + comments = relationship('ChangesetComment', + cascade="all, delete, delete-orphan") + + def is_closed(self): + return self.status == self.STATUS_CLOSED + + @property + def last_review_status(self): + return self.statuses[-1].status if self.statuses else '' + + def __json__(self): + return dict( + revisions=self.revisions + ) + + +class PullRequestReviewers(Base, BaseModel): + __tablename__ = 'pull_request_reviewers' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + def __init__(self, user=None, pull_request=None): + self.user = user + self.pull_request = pull_request + + pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True) + + user = relationship('User') + pull_request = relationship('PullRequest') + + +class Notification(Base, BaseModel): + __tablename__ = 'notifications' + __table_args__ = ( + Index('notification_type_idx', 'type'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + TYPE_CHANGESET_COMMENT = u'cs_comment' + TYPE_MESSAGE = u'message' + TYPE_MENTION = u'mention' + TYPE_REGISTRATION = u'registration' + TYPE_PULL_REQUEST = u'pull_request' + TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' + + notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) + subject = Column('subject', Unicode(512), nullable=True) + body = Column('body', UnicodeText(50000), nullable=True) + created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + type_ = Column('type', Unicode(256)) + + created_by_user = relationship('User') + notifications_to_users = relationship('UserNotification', lazy='joined', + cascade="all, delete, delete-orphan") + + @property + def recipients(self): + return [x.user for x in UserNotification.query()\ + .filter(UserNotification.notification == self)\ + .order_by(UserNotification.user_id.asc()).all()] + + @classmethod + def create(cls, created_by, subject, body, recipients, type_=None): + if type_ is None: + type_ = Notification.TYPE_MESSAGE + + notification = cls() + notification.created_by_user = created_by + notification.subject = subject + notification.body = body + notification.type_ = type_ + notification.created_on = datetime.datetime.now() + + for u in recipients: + assoc = UserNotification() + assoc.notification = notification + u.notifications.append(assoc) + Session().add(notification) + return notification + + @property + def description(self): + from kallithea.model.notification import NotificationModel + return NotificationModel().make_description(self) + + +class UserNotification(Base, BaseModel): + __tablename__ = 'user_to_notification' + __table_args__ = ( + UniqueConstraint('user_id', 'notification_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True) + notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True) + read = Column('read', Boolean, default=False) + sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None) + + user = relationship('User', lazy="joined") + notification = relationship('Notification', lazy="joined", + order_by=lambda: Notification.created_on.desc(),) + + def mark_as_read(self): + self.read = True + Session().add(self) + + +class Gist(Base, BaseModel): + __tablename__ = 'gists' + __table_args__ = ( + Index('g_gist_access_id_idx', 'gist_access_id'), + Index('g_created_on_idx', 'created_on'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + GIST_PUBLIC = u'public' + GIST_PRIVATE = u'private' + + gist_id = Column('gist_id', Integer(), primary_key=True) + gist_access_id = Column('gist_access_id', Unicode(250)) + gist_description = Column('gist_description', UnicodeText(1024)) + gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True) + gist_expires = Column('gist_expires', Float(53), nullable=False) + gist_type = Column('gist_type', Unicode(128), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + owner = relationship('User') + + @classmethod + def get_or_404(cls, id_): + res = cls.query().filter(cls.gist_access_id == id_).scalar() + if not res: + raise HTTPNotFound + return res + + @classmethod + def get_by_access_id(cls, gist_access_id): + return cls.query().filter(cls.gist_access_id == gist_access_id).scalar() + + def gist_url(self): + import kallithea + alias_url = kallithea.CONFIG.get('gist_alias_url') + if alias_url: + return alias_url.replace('{gistid}', self.gist_access_id) + + from pylons import url + return url('gist', gist_id=self.gist_access_id, qualified=True) + + @classmethod + def base_path(cls): + """ + Returns base path when all gists are stored + + :param cls: + """ + from kallithea.model.gist import GIST_STORE_LOC + q = Session().query(Ui)\ + .filter(Ui.ui_key == URL_SEP) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return os.path.join(q.one().ui_value, GIST_STORE_LOC) + + def get_api_data(self): + """ + Common function for generating gist related data for API + """ + gist = self + data = dict( + gist_id=gist.gist_id, + type=gist.gist_type, + access_id=gist.gist_access_id, + description=gist.gist_description, + url=gist.gist_url(), + expires=gist.gist_expires, + created_on=gist.created_on, + ) + return data + + def __json__(self): + data = dict( + ) + data.update(self.get_api_data()) + return data + ## SCM functions + + @property + def scm_instance(self): + from kallithea.lib.vcs import get_repo + base_path = self.base_path() + return get_repo(os.path.join(*map(safe_str, + [base_path, self.gist_access_id]))) + + +class DbMigrateVersion(Base, BaseModel): + __tablename__ = 'db_migrate_version' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + repository_id = Column('repository_id', String(250), primary_key=True) + repository_path = Column('repository_path', Text) + version = Column('version', Integer) diff --git a/kallithea/lib/dbmigrate/schema/db_2_2_0.py b/kallithea/lib/dbmigrate/schema/db_2_2_0.py new file mode 100755 --- /dev/null +++ b/kallithea/lib/dbmigrate/schema/db_2_2_0.py @@ -0,0 +1,2452 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.db +~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import os +import time +import logging +import datetime +import traceback +import hashlib +import collections +import functools + +from sqlalchemy import * +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import relationship, joinedload, class_mapper, validates +from sqlalchemy.exc import DatabaseError +from beaker.cache import cache_region, region_invalidate +from webob.exc import HTTPNotFound + +from pylons.i18n.translation import lazy_ugettext as _ + +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset + +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ + safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int, \ + get_clone_url +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache + +from kallithea.model.meta import Base, Session + +URL_SEP = '/' +log = logging.getLogger(__name__) + +from kallithea import DB_PREFIX + +#============================================================================== +# BASE CLASSES +#============================================================================== + +_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest() + + +class BaseModel(object): + """ + Base Model for all classess + """ + + @classmethod + def _get_keys(cls): + """return column names for this model """ + return class_mapper(cls).c.keys() + + def get_dict(self): + """ + return dict with keys and values corresponding + to this model data """ + + d = {} + for k in self._get_keys(): + d[k] = getattr(self, k) + + # also use __json__() if present to get additional fields + _json_attr = getattr(self, '__json__', None) + if _json_attr: + # update with attributes from __json__ + if callable(_json_attr): + _json_attr = _json_attr() + for k, val in _json_attr.iteritems(): + d[k] = val + return d + + def get_appstruct(self): + """return list with keys and values tupples corresponding + to this model data """ + + l = [] + for k in self._get_keys(): + l.append((k, getattr(self, k),)) + return l + + def populate_obj(self, populate_dict): + """populate model with data from given populate_dict""" + + for k in self._get_keys(): + if k in populate_dict: + setattr(self, k, populate_dict[k]) + + @classmethod + def query(cls): + return Session().query(cls) + + @classmethod + def get(cls, id_): + if id_: + return cls.query().get(id_) + + @classmethod + def get_or_404(cls, id_): + try: + id_ = int(id_) + except (TypeError, ValueError): + raise HTTPNotFound + + res = cls.query().get(id_) + if not res: + raise HTTPNotFound + return res + + @classmethod + def getAll(cls): + # deprecated and left for backward compatibility + return cls.get_all() + + @classmethod + def get_all(cls): + return cls.query().all() + + @classmethod + def delete(cls, id_): + obj = cls.query().get(id_) + Session().delete(obj) + + def __repr__(self): + if hasattr(self, '__unicode__'): + # python repr needs to return str + try: + return safe_str(self.__unicode__()) + except UnicodeDecodeError: + pass + return '' % (self.__class__.__name__) + + +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' + __table_args__ = ( + UniqueConstraint('app_settings_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + SETTINGS_TYPES = { + 'str': safe_str, + 'int': safe_int, + 'unicode': safe_unicode, + 'bool': str2bool, + 'list': functools.partial(aslist, sep=',') + } + DEFAULT_UPDATE_URL = '' + + app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + app_settings_name = Column("app_settings_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + _app_settings_value = Column("app_settings_value", String(4096, convert_unicode=False), nullable=True, unique=None, default=None) + _app_settings_type = Column("app_settings_type", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + + def __init__(self, key='', val='', type='unicode'): + self.app_settings_name = key + self.app_settings_value = val + self.app_settings_type = type + + @validates('_app_settings_value') + def validate_settings_value(self, key, val): + assert type(val) == unicode + return val + + @hybrid_property + def app_settings_value(self): + v = self._app_settings_value + _type = self.app_settings_type + converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode'] + return converter(v) + + @app_settings_value.setter + def app_settings_value(self, val): + """ + Setter that will always make sure we use unicode in app_settings_value + + :param val: + """ + self._app_settings_value = safe_unicode(val) + + @hybrid_property + def app_settings_type(self): + return self._app_settings_type + + @app_settings_type.setter + def app_settings_type(self, val): + if val not in self.SETTINGS_TYPES: + raise Exception('type must be one of %s got %s' + % (self.SETTINGS_TYPES.keys(), val)) + self._app_settings_type = val + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % ( + self.__class__.__name__, + self.app_settings_name, self.app_settings_value, self.app_settings_type + ) + + @classmethod + def get_by_name(cls, key): + return cls.query()\ + .filter(cls.app_settings_name == key).scalar() + + @classmethod + def get_by_name_or_create(cls, key, val='', type='unicode'): + res = cls.get_by_name(key) + if not res: + res = cls(key, val, type) + return res + + @classmethod + def create_or_update(cls, key, val=Optional(''), type=Optional('unicode')): + """ + Creates or updates Kallithea setting. If updates is triggered it will only + update parameters that are explicityl set Optional instance will be skipped + + :param key: + :param val: + :param type: + :return: + """ + res = cls.get_by_name(key) + if not res: + val = Optional.extract(val) + type = Optional.extract(type) + res = cls(key, val, type) + else: + res.app_settings_name = key + if not isinstance(val, Optional): + # update if set + res.app_settings_value = val + if not isinstance(type, Optional): + # update if set + res.app_settings_type = type + return res + + @classmethod + def get_app_settings(cls, cache=False): + + ret = cls.query() + + if cache: + ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) + + if not ret: + raise Exception('Could not get application settings !') + settings = {} + for each in ret: + settings[each.app_settings_name] = \ + each.app_settings_value + + return settings + + @classmethod + def get_auth_plugins(cls, cache=False): + auth_plugins = cls.get_by_name("auth_plugins").app_settings_value + return auth_plugins + + @classmethod + def get_auth_settings(cls, cache=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('auth_')).all() + fd = {} + for row in ret: + fd.update({row.app_settings_name: row.app_settings_value}) + + return fd + + @classmethod + def get_default_repo_settings(cls, cache=False, strip_prefix=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('default_')).all() + fd = {} + for row in ret: + key = row.app_settings_name + if strip_prefix: + key = remove_prefix(key, prefix='default_') + fd.update({key: row.app_settings_value}) + + return fd + + @classmethod + def get_server_info(cls): + import pkg_resources + import platform + import kallithea + from kallithea.lib.utils import check_git_version + mods = [(p.project_name, p.version) for p in pkg_resources.working_set] + info = { + 'modules': sorted(mods, key=lambda k: k[0].lower()), + 'py_version': platform.python_version(), + 'platform': safe_unicode(platform.platform()), + 'kallithea_version': kallithea.__version__, + 'git_version': safe_unicode(check_git_version()), + 'git_path': kallithea.CONFIG.get('git_path') + } + return info + + +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' + __table_args__ = ( + UniqueConstraint('ui_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + HOOK_UPDATE = 'changegroup.update' + HOOK_REPO_SIZE = 'changegroup.repo_size' + HOOK_PUSH = 'changegroup.push_logger' + HOOK_PRE_PUSH = 'prechangegroup.pre_push' + HOOK_PULL = 'outgoing.pull_logger' + HOOK_PRE_PULL = 'preoutgoing.pre_pull' + + ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + ui_section = Column("ui_section", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_key = Column("ui_key", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_value = Column("ui_value", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) + + # def __init__(self, section='', key='', value=''): + # self.ui_section = section + # self.ui_key = key + # self.ui_value = value + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.ui_key == key).scalar() + + @classmethod + def get_builtin_hooks(cls): + q = cls.query() + q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + return q.all() + + @classmethod + def get_custom_hooks(cls): + q = cls.query() + q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + q = q.filter(cls.ui_section == 'hooks') + return q.all() + + @classmethod + def get_repos_location(cls): + return cls.get_by_key('/').ui_value + + @classmethod + def create_or_update_hook(cls, key, val): + new_ui = cls.get_by_key(key) or cls() + new_ui.ui_section = 'hooks' + new_ui.ui_active = True + new_ui.ui_key = key + new_ui.ui_value = val + + Session().add(new_ui) + + def __repr__(self): + return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section, + self.ui_key, self.ui_value) + + +class User(Base, BaseModel): + __tablename__ = 'users' + __table_args__ = ( + UniqueConstraint('username'), UniqueConstraint('email'), + Index('u_username_idx', 'username'), + Index('u_email_idx', 'email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + DEFAULT_USER = 'default' + DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}' + + user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + username = Column("username", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + password = Column("password", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + admin = Column("admin", Boolean(), nullable=True, unique=None, default=False) + name = Column("firstname", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + lastname = Column("lastname", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) + extern_type = Column("extern_type", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + extern_name = Column("extern_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + #_user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data + + user_log = relationship('UserLog') + user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') + + repositories = relationship('Repository') + user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all') + followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all') + + repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all') + repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all') + + group_member = relationship('UserGroupMember', cascade='all') + + notifications = relationship('UserNotification', cascade='all') + # notifications assigned to this user + user_created_notifications = relationship('Notification', cascade='all') + # comments created by this user + user_comments = relationship('ChangesetComment', cascade='all') + #extra emails for this user + user_emails = relationship('UserEmailMap', cascade='all') + #extra api keys + user_api_keys = relationship('UserApiKeys', cascade='all') + + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + @property + def firstname(self): + # alias for future + return self.name + + @property + def emails(self): + other = UserEmailMap.query().filter(UserEmailMap.user==self).all() + return [self.email] + [x.email for x in other] + + @property + def api_keys(self): + other = UserApiKeys.query().filter(UserApiKeys.user==self).all() + return [self.api_key] + [x.api_key for x in other] + + @property + def ip_addresses(self): + ret = UserIpMap.query().filter(UserIpMap.user == self).all() + return [x.ip_addr for x in ret] + + @property + def username_and_name(self): + return '%s (%s %s)' % (self.username, self.firstname, self.lastname) + + @property + def full_name(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def full_name_or_username(self): + return ('%s %s' % (self.firstname, self.lastname) + if (self.firstname and self.lastname) else self.username) + + @property + def full_contact(self): + return '%s %s <%s>' % (self.firstname, self.lastname, self.email) + + @property + def short_contact(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def is_admin(self): + return self.admin + + @property + def AuthUser(self): + """ + Returns instance of AuthUser for this user + """ + from kallithea.lib.auth import AuthUser + return AuthUser(user_id=self.user_id, api_key=self.api_key, + username=self.username) + + @hybrid_property + def user_data(self): + if not self._user_data: + return {} + + try: + return json.loads(self._user_data) + except TypeError: + return {} + + @user_data.setter + def user_data(self, val): + try: + self._user_data = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.user_id, self.username) + + @classmethod + def get_by_username(cls, username, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.username.ilike(username)) + else: + q = cls.query().filter(cls.username == username) + + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(username) + ) + ) + return q.scalar() + + @classmethod + def get_by_api_key(cls, api_key, cache=False, fallback=True): + q = cls.query().filter(cls.api_key == api_key) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_api_key_%s" % api_key)) + res = q.scalar() + + if fallback and not res: + #fallback to additional keys + _res = UserApiKeys.query()\ + .filter(UserApiKeys.api_key == api_key)\ + .filter(or_(UserApiKeys.expires == -1, + UserApiKeys.expires >= time.time()))\ + .first() + if _res: + res = _res.user + return res + + @classmethod + def get_by_email(cls, email, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.email.ilike(email)) + else: + q = cls.query().filter(cls.email == email) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_key_%s" % email)) + + ret = q.scalar() + if ret is None: + q = UserEmailMap.query() + # try fetching in alternate email map + if case_insensitive: + q = q.filter(UserEmailMap.email.ilike(email)) + else: + q = q.filter(UserEmailMap.email == email) + q = q.options(joinedload(UserEmailMap.user)) + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_map_key_%s" % email)) + ret = getattr(q.scalar(), 'user', None) + + return ret + + @classmethod + def get_from_cs_author(cls, author): + """ + Tries to get User objects out of commit author string + + :param author: + """ + from kallithea.lib.helpers import email, author_name + # Valid email in the attribute passed, see if they're in the system + _email = email(author) + if _email: + user = cls.get_by_email(_email, case_insensitive=True) + if user: + return user + # Maybe we can match by username? + _author = author_name(author) + user = cls.get_by_username(_author, case_insensitive=True) + if user: + return user + + def update_lastlogin(self): + """Update user lastlogin""" + self.last_login = datetime.datetime.now() + Session().add(self) + log.debug('updated user %s lastlogin' % self.username) + + @classmethod + def get_first_admin(cls): + user = User.query().filter(User.admin == True).first() + if user is None: + raise Exception('Missing administrative account!') + return user + + @classmethod + def get_default_user(cls, cache=False): + user = User.get_by_username(User.DEFAULT_USER, cache=cache) + if user is None: + raise Exception('Missing default account!') + return user + + def get_api_data(self): + """ + Common function for generating user related data for API + """ + user = self + data = dict( + user_id=user.user_id, + username=user.username, + firstname=user.name, + lastname=user.lastname, + email=user.email, + emails=user.emails, + api_key=user.api_key, + api_keys=user.api_keys, + active=user.active, + admin=user.admin, + extern_type=user.extern_type, + extern_name=user.extern_name, + last_login=user.last_login, + ip_addresses=user.ip_addresses + ) + return data + + def __json__(self): + data = dict( + full_name=self.full_name, + full_name_or_username=self.full_name_or_username, + short_contact=self.short_contact, + full_contact=self.full_contact + ) + data.update(self.get_api_data()) + return data + + +class UserApiKeys(Base, BaseModel): + __tablename__ = 'user_api_keys' + __table_args__ = ( + Index('uak_api_key_idx', 'api_key'), + Index('uak_api_key_expires_idx', 'api_key', 'expires'), + UniqueConstraint('api_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False), nullable=False, unique=True) + description = Column('description', UnicodeText(1024)) + expires = Column('expires', Float(53), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + user = relationship('User', lazy='joined') + + @property + def expired(self): + if self.expires == -1: + return False + return time.time() > self.expires + + +class UserEmailMap(Base, BaseModel): + __tablename__ = 'user_email_map' + __table_args__ = ( + Index('uem_email_idx', 'email'), + UniqueConstraint('email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False), nullable=True, unique=False, default=None) + user = relationship('User', lazy='joined') + + @validates('_email') + def validate_email(self, key, email): + # check if this email is not main one + main_email = Session().query(User).filter(User.email == email).scalar() + if main_email is not None: + raise AttributeError('email %s is present is user table' % email) + return email + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + +class UserIpMap(Base, BaseModel): + __tablename__ = 'user_ip_map' + __table_args__ = ( + UniqueConstraint('user_id', 'ip_addr'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + ip_addr = Column("ip_addr", String(255, convert_unicode=False), nullable=True, unique=False, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + user = relationship('User', lazy='joined') + + @classmethod + def _get_ip_range(cls, ip_addr): + from kallithea.lib import ipaddr + net = ipaddr.IPNetwork(address=ip_addr) + return [str(net.network), str(net.broadcast)] + + def __json__(self): + return dict( + ip_addr=self.ip_addr, + ip_range=self._get_ip_range(self.ip_addr) + ) + + def __unicode__(self): + return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__, + self.user_id, self.ip_addr) + +class UserLog(Base, BaseModel): + __tablename__ = 'user_logs' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + username = Column("username", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True) + repository_name = Column("repository_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + user_ip = Column("user_ip", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + action = Column("action", UnicodeText(1200000, convert_unicode=False), nullable=True, unique=None, default=None) + action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.repository_name, + self.action) + + @property + def action_as_day(self): + return datetime.date(*self.action_date.timetuple()[:3]) + + user = relationship('User') + repository = relationship('Repository', cascade='') + + +class UserGroup(Base, BaseModel): + __tablename__ = 'users_groups' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_name = Column("users_group_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None) + user_group_description = Column("user_group_description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None) + users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined") + users_group_to_perm = relationship('UserGroupToPerm', cascade='all') + users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all') + user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all') + + user = relationship('User') + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.users_group_id, + self.users_group_name) + + @classmethod + def get_by_group_name(cls, group_name, cache=False, + case_insensitive=False): + if case_insensitive: + q = cls.query().filter(cls.users_group_name.ilike(group_name)) + else: + q = cls.query().filter(cls.users_group_name == group_name) + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(group_name) + ) + ) + return q.scalar() + + @classmethod + def get(cls, user_group_id, cache=False): + user_group = cls.query() + if cache: + user_group = user_group.options(FromCache("sql_cache_short", + "get_users_group_%s" % user_group_id)) + return user_group.get(user_group_id) + + def get_api_data(self, with_members=True): + user_group = self + + data = dict( + users_group_id=user_group.users_group_id, + group_name=user_group.users_group_name, + group_description=user_group.user_group_description, + active=user_group.users_group_active, + owner=user_group.user.username, + ) + if with_members: + members = [] + for user in user_group.members: + user = user.user + members.append(user.get_api_data()) + data['members'] = members + + return data + + +class UserGroupMember(Base, BaseModel): + __tablename__ = 'users_groups_members' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + + user = relationship('User', lazy='joined') + users_group = relationship('UserGroup') + + def __init__(self, gr_id='', u_id=''): + self.users_group_id = gr_id + self.user_id = u_id + + +class RepositoryField(Base, BaseModel): + __tablename__ = 'repositories_fields' + __table_args__ = ( + UniqueConstraint('repository_id', 'field_key'), # no-multi field + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields + + repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + field_key = Column("field_key", String(250, convert_unicode=False)) + field_label = Column("field_label", String(1024, convert_unicode=False), nullable=False) + field_value = Column("field_value", String(10000, convert_unicode=False), nullable=False) + field_desc = Column("field_desc", String(1024, convert_unicode=False), nullable=False) + field_type = Column("field_type", String(256), nullable=False, unique=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repository = relationship('Repository') + + @property + def field_key_prefixed(self): + return 'ex_%s' % self.field_key + + @classmethod + def un_prefix_key(cls, key): + if key.startswith(cls.PREFIX): + return key[len(cls.PREFIX):] + return key + + @classmethod + def get_by_key_name(cls, key, repo): + row = cls.query()\ + .filter(cls.repository == repo)\ + .filter(cls.field_key == key).scalar() + return row + + +class Repository(Base, BaseModel): + __tablename__ = 'repositories' + __table_args__ = ( + UniqueConstraint('repo_name'), + Index('r_repo_name_idx', 'repo_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}' + DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}' + + STATE_CREATED = 'repo_state_created' + STATE_PENDING = 'repo_state_pending' + STATE_ERROR = 'repo_state_error' + + repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repo_name = Column("repo_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None) + clone_uri = Column("clone_uri", String(255, convert_unicode=False), nullable=True, unique=False, default=None) + repo_type = Column("repo_type", String(255, convert_unicode=False), nullable=False, unique=False, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + private = Column("private", Boolean(), nullable=True, unique=None, default=None) + enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True) + enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True) + description = Column("description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + _landing_revision = Column("landing_revision", String(255, convert_unicode=False), nullable=False, unique=False, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + _locked = Column("locked", String(255, convert_unicode=False), nullable=True, unique=False, default=None) + _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data + + fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) + + user = relationship('User') + fork = relationship('Repository', remote_side=repo_id) + group = relationship('RepoGroup') + repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + stats = relationship('Statistics', cascade='all', uselist=False) + + followers = relationship('UserFollowing', + primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', + cascade='all') + extra_fields = relationship('RepositoryField', + cascade="all, delete, delete-orphan") + + logs = relationship('UserLog') + comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan") + + pull_requests_org = relationship('PullRequest', + primaryjoin='PullRequest.org_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + pull_requests_other = relationship('PullRequest', + primaryjoin='PullRequest.other_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, + safe_unicode(self.repo_name)) + + @hybrid_property + def landing_rev(self): + # always should return [rev_type, rev] + if self._landing_revision: + _rev_info = self._landing_revision.split(':') + if len(_rev_info) < 2: + _rev_info.insert(0, 'rev') + return [_rev_info[0], _rev_info[1]] + return [None, None] + + @landing_rev.setter + def landing_rev(self, val): + if ':' not in val: + raise ValueError('value must be delimited with `:` and consist ' + 'of :, got %s instead' % val) + self._landing_revision = val + + @hybrid_property + def locked(self): + # always should return [user_id, timelocked] + if self._locked: + _lock_info = self._locked.split(':') + return int(_lock_info[0]), _lock_info[1] + return [None, None] + + @locked.setter + def locked(self, val): + if val and isinstance(val, (list, tuple)): + self._locked = ':'.join(map(str, val)) + else: + self._locked = None + + @hybrid_property + def changeset_cache(self): + from kallithea.lib.vcs.backends.base import EmptyChangeset + dummy = EmptyChangeset().__json__() + if not self._changeset_cache: + return dummy + try: + return json.loads(self._changeset_cache) + except TypeError: + return dummy + + @changeset_cache.setter + def changeset_cache(self, val): + try: + self._changeset_cache = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def normalize_repo_name(cls, repo_name): + """ + Normalizes os specific repo_name to the format internally stored inside + dabatabase using URL_SEP + + :param cls: + :param repo_name: + """ + return cls.url_sep().join(repo_name.split(os.sep)) + + @classmethod + def get_by_repo_name(cls, repo_name): + q = Session().query(cls).filter(cls.repo_name == repo_name) + q = q.options(joinedload(Repository.fork))\ + .options(joinedload(Repository.user))\ + .options(joinedload(Repository.group)) + return q.scalar() + + @classmethod + def get_by_full_path(cls, repo_full_path): + repo_name = repo_full_path.split(cls.base_path(), 1)[-1] + repo_name = cls.normalize_repo_name(repo_name) + return cls.get_by_repo_name(repo_name.strip(URL_SEP)) + + @classmethod + def get_repo_forks(cls, repo_id): + return cls.query().filter(Repository.fork_id == repo_id) + + @classmethod + def base_path(cls): + """ + Returns base path when all repos are stored + + :param cls: + """ + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def forks(self): + """ + Return forks of this repo + """ + return Repository.get_repo_forks(self.repo_id) + + @property + def parent(self): + """ + Returns fork parent + """ + return self.fork + + @property + def just_name(self): + return self.repo_name.split(Repository.url_sep())[-1] + + @property + def groups_with_parents(self): + groups = [] + if self.group is None: + return groups + + cur_gr = self.group + groups.insert(0, cur_gr) + while 1: + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + groups.insert(0, gr) + + return groups + + @property + def groups_and_repo(self): + return self.groups_with_parents, self.just_name, self.repo_name + + @LazyProperty + def repo_path(self): + """ + Returns base full path for that repository means where it actually + exists on a filesystem + """ + q = Session().query(Ui).filter(Ui.ui_key == + Repository.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def repo_full_path(self): + p = [self.repo_path] + # we need to split the name by / since this is how we store the + # names in the database, but that eventually needs to be converted + # into a valid system path + p += self.repo_name.split(Repository.url_sep()) + return os.path.join(*map(safe_unicode, p)) + + @property + def cache_keys(self): + """ + Returns associated cache keys for that repo + """ + return CacheInvalidation.query()\ + .filter(CacheInvalidation.cache_args == self.repo_name)\ + .order_by(CacheInvalidation.cache_key)\ + .all() + + def get_new_name(self, repo_name): + """ + returns new full repository name based on assigned group and new new + + :param group_name: + """ + path_prefix = self.group.full_path_splitted if self.group else [] + return Repository.url_sep().join(path_prefix + [repo_name]) + + @property + def _ui(self): + """ + Creates an db based ui object for this repository + """ + from kallithea.lib.utils import make_ui + return make_ui('db', clear_session=False) + + @classmethod + def is_valid(cls, repo_name): + """ + returns True if given repo name is a valid filesystem repository + + :param cls: + :param repo_name: + """ + from kallithea.lib.utils import is_valid_repo + + return is_valid_repo(repo_name, cls.base_path()) + + def get_api_data(self): + """ + Common function for generating repo api data + + """ + repo = self + data = dict( + repo_id=repo.repo_id, + repo_name=repo.repo_name, + repo_type=repo.repo_type, + clone_uri=repo.clone_uri, + private=repo.private, + created_on=repo.created_on, + description=repo.description, + landing_rev=repo.landing_rev, + owner=repo.user.username, + fork_of=repo.fork.repo_name if repo.fork else None, + enable_statistics=repo.enable_statistics, + enable_locking=repo.enable_locking, + enable_downloads=repo.enable_downloads, + last_changeset=repo.changeset_cache, + locked_by=User.get(self.locked[0]).get_api_data() \ + if self.locked[0] else None, + locked_date=time_to_datetime(self.locked[1]) \ + if self.locked[1] else None + ) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) + if repository_fields: + for f in self.extra_fields: + data[f.field_key_prefixed] = f.field_value + + return data + + @classmethod + def lock(cls, repo, user_id, lock_time=None): + if not lock_time: + lock_time = time.time() + repo.locked = [user_id, lock_time] + Session().add(repo) + Session().commit() + + @classmethod + def unlock(cls, repo): + repo.locked = None + Session().add(repo) + Session().commit() + + @classmethod + def getlock(cls, repo): + return repo.locked + + @property + def last_db_change(self): + return self.updated_on + + def clone_url(self, **override): + from pylons import url + qualified_home_url = url('home', qualified=True) + + uri_tmpl = None + if 'uri_tmpl' in override: + uri_tmpl = override['uri_tmpl'] + del override['uri_tmpl'] + + # we didn't override our tmpl from **overrides + if not uri_tmpl: + uri_tmpl = self.DEFAULT_CLONE_URI + try: + from pylons import tmpl_context as c + uri_tmpl = c.clone_uri_tmpl + except Exception: + # in any case if we call this outside of request context, + # ie, not having tmpl_context set up + pass + + return get_clone_url(uri_tmpl=uri_tmpl, + qualifed_home_url=qualified_home_url, + repo_name=self.repo_name, + repo_id=self.repo_id, **override) + + #========================================================================== + # SCM PROPERTIES + #========================================================================== + + def get_changeset(self, rev=None): + return get_changeset_safe(self.scm_instance, rev) + + def get_landing_changeset(self): + """ + Returns landing changeset, or if that doesn't exist returns the tip + """ + _rev_type, _rev = self.landing_rev + cs = self.get_changeset(_rev) + if isinstance(cs, EmptyChangeset): + return self.get_changeset() + return cs + + def update_changeset_cache(self, cs_cache=None): + """ + Update cache of last changeset for repository, keys should be:: + + short_id + raw_id + revision + message + date + author + + :param cs_cache: + """ + from kallithea.lib.vcs.backends.base import BaseChangeset + if cs_cache is None: + cs_cache = EmptyChangeset() + # use no-cache version here + scm_repo = self.scm_instance_no_cache() + if scm_repo: + cs_cache = scm_repo.get_changeset() + + if isinstance(cs_cache, BaseChangeset): + cs_cache = cs_cache.__json__() + + if (cs_cache != self.changeset_cache or not self.changeset_cache): + _default = datetime.datetime.fromtimestamp(0) + last_change = cs_cache.get('date') or _default + log.debug('updated repo %s with new cs cache %s' + % (self.repo_name, cs_cache)) + self.updated_on = last_change + self.changeset_cache = cs_cache + Session().add(self) + Session().commit() + else: + log.debug('Skipping repo:%s already with latest changes' + % self.repo_name) + + @property + def tip(self): + return self.get_changeset('tip') + + @property + def author(self): + return self.tip.author + + @property + def last_change(self): + return self.scm_instance.last_change + + def get_comments(self, revisions=None): + """ + Returns comments for this repository grouped by revisions + + :param revisions: filter query by revisions only + """ + cmts = ChangesetComment.query()\ + .filter(ChangesetComment.repo == self) + if revisions: + cmts = cmts.filter(ChangesetComment.revision.in_(revisions)) + grouped = collections.defaultdict(list) + for cmt in cmts.all(): + grouped[cmt.revision].append(cmt) + return grouped + + def statuses(self, revisions=None): + """ + Returns statuses for this repository + + :param revisions: list of revisions to get statuses for + """ + + statuses = ChangesetStatus.query()\ + .filter(ChangesetStatus.repo == self)\ + .filter(ChangesetStatus.version == 0) + if revisions: + statuses = statuses.filter(ChangesetStatus.revision.in_(revisions)) + grouped = {} + + #maybe we have open new pullrequest without a status ? + stat = ChangesetStatus.STATUS_UNDER_REVIEW + status_lbl = ChangesetStatus.get_status_lbl(stat) + for pr in PullRequest.query().filter(PullRequest.org_repo == self).all(): + for rev in pr.revisions: + pr_id = pr.pull_request_id + pr_repo = pr.other_repo.repo_name + grouped[rev] = [stat, status_lbl, pr_id, pr_repo] + + for stat in statuses.all(): + pr_id = pr_repo = None + if stat.pull_request: + pr_id = stat.pull_request.pull_request_id + pr_repo = stat.pull_request.other_repo.repo_name + grouped[stat.revision] = [str(stat.status), stat.status_lbl, + pr_id, pr_repo] + return grouped + + def _repo_size(self): + from kallithea.lib import helpers as h + log.debug('calculating repository size...') + return h.format_byte_size(self.scm_instance.size) + + #========================================================================== + # SCM CACHE INSTANCE + #========================================================================== + + def set_invalidate(self): + """ + Mark caches of this repo as invalid. + """ + CacheInvalidation.set_invalidate(self.repo_name) + + def scm_instance_no_cache(self): + return self.__get_instance() + + @property + def scm_instance(self): + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) + if full_cache: + return self.scm_instance_cached() + return self.__get_instance() + + def scm_instance_cached(self, valid_cache_keys=None): + @cache_region('long_term') + def _c(repo_name): + return self.__get_instance() + rn = self.repo_name + + valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys) + if not valid: + log.debug('Cache for %s invalidated, getting new object' % (rn)) + region_invalidate(_c, None, rn) + else: + log.debug('Getting obj for %s from cache' % (rn)) + return _c(rn) + + def __get_instance(self): + repo_full_path = self.repo_full_path + try: + alias = get_scm(repo_full_path)[0] + log.debug('Creating instance of %s repository from %s' + % (alias, repo_full_path)) + backend = get_backend(alias) + except VCSError: + log.error(traceback.format_exc()) + log.error('Perhaps this repository is in db and not in ' + 'filesystem run rescan repositories with ' + '"destroy old data " option from admin panel') + return + + if alias == 'hg': + + repo = backend(safe_str(repo_full_path), create=False, + baseui=self._ui) + # skip hidden web repository + if repo._get_hidden(): + return + else: + repo = backend(repo_full_path, create=False) + + return repo + + def __json__(self): + return dict(landing_rev = self.landing_rev) + +class RepoGroup(Base, BaseModel): + __tablename__ = 'groups' + __table_args__ = ( + UniqueConstraint('group_name', 'group_parent_id'), + CheckConstraint('group_id != group_parent_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + __mapper_args__ = {'order_by': 'group_name'} + + SEP = ' » ' + + group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + group_name = Column("group_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None) + group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) + group_description = Column("group_description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + parent_group = relationship('RepoGroup', remote_side=group_id) + user = relationship('User') + + def __init__(self, group_name='', parent_group=None): + self.group_name = group_name + self.parent_group = parent_group + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id, + self.group_name) + + @classmethod + def _generate_choice(cls, repo_group): + from webhelpers.html import literal as _literal + _name = lambda k: _literal(cls.SEP.join(k)) + return repo_group.group_id, _name(repo_group.full_path_splitted) + + @classmethod + def groups_choices(cls, groups=None, show_empty_group=True): + if not groups: + groups = cls.query().all() + + repo_groups = [] + if show_empty_group: + repo_groups = [('-1', u'-- %s --' % _('top level'))] + + repo_groups.extend([cls._generate_choice(x) for x in groups]) + + repo_groups = sorted(repo_groups, key=lambda t: t[1].split(cls.SEP)[0]) + return repo_groups + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): + if case_insensitive: + gr = cls.query()\ + .filter(cls.group_name.ilike(group_name)) + else: + gr = cls.query()\ + .filter(cls.group_name == group_name) + if cache: + gr = gr.options(FromCache( + "sql_cache_short", + "get_group_%s" % _hash_key(group_name) + ) + ) + return gr.scalar() + + @property + def parents(self): + parents_recursion_limit = 5 + groups = [] + if self.parent_group is None: + return groups + cur_gr = self.parent_group + groups.insert(0, cur_gr) + cnt = 0 + while 1: + cnt += 1 + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + if cnt == parents_recursion_limit: + # this will prevent accidental infinit loops + log.error('group nested more than %s' % + parents_recursion_limit) + break + + groups.insert(0, gr) + return groups + + @property + def children(self): + return RepoGroup.query().filter(RepoGroup.parent_group == self) + + @property + def name(self): + return self.group_name.split(RepoGroup.url_sep())[-1] + + @property + def full_path(self): + return self.group_name + + @property + def full_path_splitted(self): + return self.group_name.split(RepoGroup.url_sep()) + + @property + def repositories(self): + return Repository.query()\ + .filter(Repository.group == self)\ + .order_by(Repository.repo_name) + + @property + def repositories_recursive_count(self): + cnt = self.repositories.count() + + def children_count(group): + cnt = 0 + for child in group.children: + cnt += child.repositories.count() + cnt += children_count(child) + return cnt + + return cnt + children_count(self) + + def _recursive_objects(self, include_repos=True): + all_ = [] + + def _get_members(root_gr): + if include_repos: + for r in root_gr.repositories: + all_.append(r) + childs = root_gr.children.all() + if childs: + for gr in childs: + all_.append(gr) + _get_members(gr) + + _get_members(self) + return [self] + all_ + + def recursive_groups_and_repos(self): + """ + Recursive return all groups, with repositories in those groups + """ + return self._recursive_objects() + + def recursive_groups(self): + """ + Returns all children groups for this group including children of children + """ + return self._recursive_objects(include_repos=False) + + def get_new_name(self, group_name): + """ + returns new full group name based on parent and new name + + :param group_name: + """ + path_prefix = (self.parent_group.full_path_splitted if + self.parent_group else []) + return RepoGroup.url_sep().join(path_prefix + [group_name]) + + def get_api_data(self): + """ + Common function for generating api data + + """ + group = self + data = dict( + group_id=group.group_id, + group_name=group.group_name, + group_description=group.group_description, + parent_group=group.parent_group.group_name if group.parent_group else None, + repositories=[x.repo_name for x in group.repositories], + owner=group.user.username + ) + return data + + +class Permission(Base, BaseModel): + __tablename__ = 'permissions' + __table_args__ = ( + Index('p_perm_name_idx', 'permission_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PERMS = [ + ('hg.admin', _('Kallithea Administrator')), + + ('repository.none', _('Repository no access')), + ('repository.read', _('Repository read access')), + ('repository.write', _('Repository write access')), + ('repository.admin', _('Repository admin access')), + + ('group.none', _('Repository group no access')), + ('group.read', _('Repository group read access')), + ('group.write', _('Repository group write access')), + ('group.admin', _('Repository group admin access')), + + ('usergroup.none', _('User group no access')), + ('usergroup.read', _('User group read access')), + ('usergroup.write', _('User group write access')), + ('usergroup.admin', _('User group admin access')), + + ('hg.repogroup.create.false', _('Repository Group creation disabled')), + ('hg.repogroup.create.true', _('Repository Group creation enabled')), + + ('hg.usergroup.create.false', _('User Group creation disabled')), + ('hg.usergroup.create.true', _('User Group creation enabled')), + + ('hg.create.none', _('Repository creation disabled')), + ('hg.create.repository', _('Repository creation enabled')), + ('hg.create.write_on_repogroup.true', _('Repository creation enabled with write permission to a repository group')), + ('hg.create.write_on_repogroup.false', _('Repository creation disabled with write permission to a repository group')), + + ('hg.fork.none', _('Repository forking disabled')), + ('hg.fork.repository', _('Repository forking enabled')), + + ('hg.register.none', _('Registration disabled')), + ('hg.register.manual_activate', _('User Registration with manual account activation')), + ('hg.register.auto_activate', _('User Registration with automatic account activation')), + + ('hg.extern_activate.manual', _('Manual activation of external account')), + ('hg.extern_activate.auto', _('Automatic activation of external account')), + + ] + + #definition of system default permissions for DEFAULT user + DEFAULT_USER_PERMISSIONS = [ + 'repository.read', + 'group.read', + 'usergroup.read', + 'hg.create.repository', + 'hg.create.write_on_repogroup.true', + 'hg.fork.repository', + 'hg.register.manual_activate', + 'hg.extern_activate.auto', + ] + + # defines which permissions are more important higher the more important + # Weight defines which permissions are more important. + # The higher number the more important. + PERM_WEIGHTS = { + 'repository.none': 0, + 'repository.read': 1, + 'repository.write': 3, + 'repository.admin': 4, + + 'group.none': 0, + 'group.read': 1, + 'group.write': 3, + 'group.admin': 4, + + 'usergroup.none': 0, + 'usergroup.read': 1, + 'usergroup.write': 3, + 'usergroup.admin': 4, + 'hg.repogroup.create.false': 0, + 'hg.repogroup.create.true': 1, + + 'hg.usergroup.create.false': 0, + 'hg.usergroup.create.true': 1, + + 'hg.fork.none': 0, + 'hg.fork.repository': 1, + 'hg.create.none': 0, + 'hg.create.repository': 1 + } + + permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + permission_name = Column("permission_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + permission_longname = Column("permission_longname", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, self.permission_id, self.permission_name + ) + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.permission_name == key).scalar() + + @classmethod + def get_default_perms(cls, default_user_id): + q = Session().query(UserRepoToPerm, Repository, cls)\ + .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ + .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_group_perms(cls, default_user_id): + q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\ + .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\ + .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoGroupToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_user_group_perms(cls, default_user_id): + q = Session().query(UserUserGroupToPerm, UserGroup, cls)\ + .join((UserGroup, UserUserGroupToPerm.user_group_id == UserGroup.users_group_id))\ + .join((cls, UserUserGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserUserGroupToPerm.user_id == default_user_id) + + return q.all() + + +class UserRepoToPerm(Base, BaseModel): + __tablename__ = 'repo_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'repository_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + repository = relationship('Repository') + permission = relationship('Permission') + + @classmethod + def create(cls, user, repository, permission): + n = cls() + n.user = user + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.repository) + + +class UserUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'user_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + user_group = relationship('UserGroup') + permission = relationship('Permission') + + @classmethod + def create(cls, user, user_group, permission): + n = cls() + n.user = user + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.user_group) + + +class UserToPerm(Base, BaseModel): + __tablename__ = 'user_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + permission = relationship('Permission', lazy='joined') + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.permission) + + +class UserGroupRepoToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_to_perm' + __table_args__ = ( + UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + repository = relationship('Repository') + + @classmethod + def create(cls, users_group, repository, permission): + n = cls() + n.users_group = users_group + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.users_group, self.repository) + + +class UserGroupUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_group_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'), + CheckConstraint('target_user_group_id != user_group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id') + user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id') + permission = relationship('Permission') + + @classmethod + def create(cls, target_user_group, user_group, permission): + n = cls() + n.target_user_group = target_user_group + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.target_user_group, self.user_group) + + +class UserGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'permission_id',), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + + +class UserRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'user_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + group = relationship('RepoGroup') + permission = relationship('Permission') + + +class UserGroupRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + group = relationship('RepoGroup') + + +class Statistics(Base, BaseModel): + __tablename__ = 'statistics' + __table_args__ = ( + UniqueConstraint('repository_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) + stat_on_revision = Column("stat_on_revision", Integer(), nullable=False) + commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data + commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data + languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data + + repository = relationship('Repository', single_parent=True) + + +class UserFollowing(Base, BaseModel): + __tablename__ = 'user_followings' + __table_args__ = ( + UniqueConstraint('user_id', 'follows_repository_id'), + UniqueConstraint('user_id', 'follows_user_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None) + follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + + user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') + + follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') + follows_repository = relationship('Repository', order_by='Repository.repo_name') + + @classmethod + def get_repo_followers(cls, repo_id): + return cls.query().filter(cls.follows_repo_id == repo_id) + + +class CacheInvalidation(Base, BaseModel): + __tablename__ = 'cache_invalidation' + __table_args__ = ( + UniqueConstraint('cache_key'), + Index('key_idx', 'cache_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + # cache_id, not used + cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + # cache_key as created by _get_cache_key + cache_key = Column("cache_key", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + # cache_args is a repo_name + cache_args = Column("cache_args", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + # instance sets cache_active True when it is caching, + # other instances set cache_active to False to indicate that this cache is invalid + cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False) + + def __init__(self, cache_key, repo_name=''): + self.cache_key = cache_key + self.cache_args = repo_name + self.cache_active = False + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % (self.__class__.__name__, + self.cache_id, self.cache_key, self.cache_active) + + def _cache_key_partition(self): + prefix, repo_name, suffix = self.cache_key.partition(self.cache_args) + return prefix, repo_name, suffix + + def get_prefix(self): + """ + get prefix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[0] + + def get_suffix(self): + """ + get suffix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[2] + + @classmethod + def clear_cache(cls): + """ + Delete all cache keys from database. + Should only be run when all instances are down and all entries thus stale. + """ + cls.query().delete() + Session().commit() + + @classmethod + def _get_cache_key(cls, key): + """ + Wrapper for generating a unique cache key for this instance and "key". + key must / will start with a repo_name which will be stored in .cache_args . + """ + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') + return "%s%s" % (prefix, key) + + @classmethod + def set_invalidate(cls, repo_name, delete=False): + """ + Mark all caches of a repo as invalid in the database. + """ + inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all() + log.debug('for repo %s got %s invalidation objects' % (repo_name, inv_objs)) + try: + for inv_obj in inv_objs: + log.debug('marking %s key for invalidation based on repo_name=%s' + % (inv_obj, safe_str(repo_name))) + if delete: + Session().delete(inv_obj) + else: + inv_obj.cache_active = False + Session().add(inv_obj) + Session().commit() + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + + @classmethod + def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None): + """ + Mark this cache key as active and currently cached. + Return True if the existing cache registration still was valid. + Return False to indicate that it had been invalidated and caches should be refreshed. + """ + + key = (repo_name + '_' + kind) if kind else repo_name + cache_key = cls._get_cache_key(key) + + if valid_cache_keys and cache_key in valid_cache_keys: + return True + + try: + inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar() + if not inv_obj: + inv_obj = CacheInvalidation(cache_key, repo_name) + was_valid = inv_obj.cache_active + inv_obj.cache_active = True + Session().add(inv_obj) + Session().commit() + return was_valid + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + return False + + @classmethod + def get_valid_cache_keys(cls): + """ + Return opaque object with information of which caches still are valid + and can be used without checking for invalidation. + """ + return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all()) + + +class ChangesetComment(Base, BaseModel): + __tablename__ = 'changeset_comments' + __table_args__ = ( + Index('cc_revision_idx', 'revision'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + revision = Column('revision', String(40), nullable=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + line_no = Column('line_no', Unicode(10), nullable=True) + hl_lines = Column('hl_lines', Unicode(512), nullable=True) + f_path = Column('f_path', Unicode(1000), nullable=True) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) + text = Column('text', UnicodeText(25000), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan") + pull_request = relationship('PullRequest', lazy='joined') + + @classmethod + def get_users(cls, revision=None, pull_request_id=None): + """ + Returns user associated with this ChangesetComment. ie those + who actually commented + + :param cls: + :param revision: + """ + q = Session().query(User)\ + .join(ChangesetComment.author) + if revision: + q = q.filter(cls.revision == revision) + elif pull_request_id: + q = q.filter(cls.pull_request_id == pull_request_id) + return q.all() + + +class ChangesetStatus(Base, BaseModel): + __tablename__ = 'changeset_statuses' + __table_args__ = ( + Index('cs_revision_idx', 'revision'), + Index('cs_version_idx', 'version'), + UniqueConstraint('repo_id', 'revision', 'version'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed' + STATUS_APPROVED = 'approved' + STATUS_REJECTED = 'rejected' + STATUS_UNDER_REVIEW = 'under_review' + + STATUSES = [ + (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default + (STATUS_APPROVED, _("Approved")), + (STATUS_REJECTED, _("Rejected")), + (STATUS_UNDER_REVIEW, _("Under Review")), + ] + + changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + revision = Column('revision', String(40), nullable=False) + status = Column('status', String(128), nullable=False, default=DEFAULT) + changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id')) + modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now) + version = Column('version', Integer(), nullable=False, default=0) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + comment = relationship('ChangesetComment', lazy='joined') + pull_request = relationship('PullRequest', lazy='joined') + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, + self.status, self.author + ) + + @classmethod + def get_status_lbl(cls, value): + return dict(cls.STATUSES).get(value) + + @property + def status_lbl(self): + return ChangesetStatus.get_status_lbl(self.status) + + +class PullRequest(Base, BaseModel): + __tablename__ = 'pull_requests' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + # values for .status + STATUS_NEW = u'new' + STATUS_OPEN = u'open' + STATUS_CLOSED = u'closed' + + pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) + title = Column('title', Unicode(256), nullable=True) + description = Column('description', UnicodeText(10240), nullable=True) + status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW) # only for closedness, not approve/reject/etc + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max + org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + org_ref = Column('org_ref', Unicode(256), nullable=False) + other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + other_ref = Column('other_ref', Unicode(256), nullable=False) + + @hybrid_property + def revisions(self): + return self._revisions.split(':') + + @revisions.setter + def revisions(self, val): + self._revisions = ':'.join(val) + + @property + def org_ref_parts(self): + return self.org_ref.split(':') + + @property + def other_ref_parts(self): + return self.other_ref.split(':') + + author = relationship('User', lazy='joined') + reviewers = relationship('PullRequestReviewers', + cascade="all, delete, delete-orphan") + org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') + other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id') + statuses = relationship('ChangesetStatus') + comments = relationship('ChangesetComment', + cascade="all, delete, delete-orphan") + + def is_closed(self): + return self.status == self.STATUS_CLOSED + + @property + def last_review_status(self): + return self.statuses[-1].status if self.statuses else '' + + def __json__(self): + return dict( + revisions=self.revisions + ) + + +class PullRequestReviewers(Base, BaseModel): + __tablename__ = 'pull_request_reviewers' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + def __init__(self, user=None, pull_request=None): + self.user = user + self.pull_request = pull_request + + pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True) + + user = relationship('User') + pull_request = relationship('PullRequest') + + +class Notification(Base, BaseModel): + __tablename__ = 'notifications' + __table_args__ = ( + Index('notification_type_idx', 'type'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + TYPE_CHANGESET_COMMENT = u'cs_comment' + TYPE_MESSAGE = u'message' + TYPE_MENTION = u'mention' + TYPE_REGISTRATION = u'registration' + TYPE_PULL_REQUEST = u'pull_request' + TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' + + notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) + subject = Column('subject', Unicode(512), nullable=True) + body = Column('body', UnicodeText(50000), nullable=True) + created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + type_ = Column('type', Unicode(256)) + + created_by_user = relationship('User') + notifications_to_users = relationship('UserNotification', lazy='joined', + cascade="all, delete, delete-orphan") + + @property + def recipients(self): + return [x.user for x in UserNotification.query()\ + .filter(UserNotification.notification == self)\ + .order_by(UserNotification.user_id.asc()).all()] + + @classmethod + def create(cls, created_by, subject, body, recipients, type_=None): + if type_ is None: + type_ = Notification.TYPE_MESSAGE + + notification = cls() + notification.created_by_user = created_by + notification.subject = subject + notification.body = body + notification.type_ = type_ + notification.created_on = datetime.datetime.now() + + for u in recipients: + assoc = UserNotification() + assoc.notification = notification + u.notifications.append(assoc) + Session().add(notification) + return notification + + @property + def description(self): + from kallithea.model.notification import NotificationModel + return NotificationModel().make_description(self) + + +class UserNotification(Base, BaseModel): + __tablename__ = 'user_to_notification' + __table_args__ = ( + UniqueConstraint('user_id', 'notification_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True) + notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True) + read = Column('read', Boolean, default=False) + sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None) + + user = relationship('User', lazy="joined") + notification = relationship('Notification', lazy="joined", + order_by=lambda: Notification.created_on.desc(),) + + def mark_as_read(self): + self.read = True + Session().add(self) + + +class Gist(Base, BaseModel): + __tablename__ = 'gists' + __table_args__ = ( + Index('g_gist_access_id_idx', 'gist_access_id'), + Index('g_created_on_idx', 'created_on'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + GIST_PUBLIC = u'public' + GIST_PRIVATE = u'private' + DEFAULT_FILENAME = u'gistfile1.txt' + + gist_id = Column('gist_id', Integer(), primary_key=True) + gist_access_id = Column('gist_access_id', Unicode(250)) + gist_description = Column('gist_description', UnicodeText(1024)) + gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True) + gist_expires = Column('gist_expires', Float(53), nullable=False) + gist_type = Column('gist_type', Unicode(128), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + owner = relationship('User') + + def __repr__(self): + return '' % (self.gist_type, self.gist_access_id) + + @classmethod + def get_or_404(cls, id_): + res = cls.query().filter(cls.gist_access_id == id_).scalar() + if not res: + raise HTTPNotFound + return res + + @classmethod + def get_by_access_id(cls, gist_access_id): + return cls.query().filter(cls.gist_access_id == gist_access_id).scalar() + + def gist_url(self): + import kallithea + alias_url = kallithea.CONFIG.get('gist_alias_url') + if alias_url: + return alias_url.replace('{gistid}', self.gist_access_id) + + from pylons import url + return url('gist', gist_id=self.gist_access_id, qualified=True) + + @classmethod + def base_path(cls): + """ + Returns base path when all gists are stored + + :param cls: + """ + from kallithea.model.gist import GIST_STORE_LOC + q = Session().query(Ui)\ + .filter(Ui.ui_key == URL_SEP) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return os.path.join(q.one().ui_value, GIST_STORE_LOC) + + def get_api_data(self): + """ + Common function for generating gist related data for API + """ + gist = self + data = dict( + gist_id=gist.gist_id, + type=gist.gist_type, + access_id=gist.gist_access_id, + description=gist.gist_description, + url=gist.gist_url(), + expires=gist.gist_expires, + created_on=gist.created_on, + ) + return data + + def __json__(self): + data = dict( + ) + data.update(self.get_api_data()) + return data + ## SCM functions + + @property + def scm_instance(self): + from kallithea.lib.vcs import get_repo + base_path = self.base_path() + return get_repo(os.path.join(*map(safe_str, + [base_path, self.gist_access_id]))) + + +class DbMigrateVersion(Base, BaseModel): + __tablename__ = 'db_migrate_version' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + repository_id = Column('repository_id', String(250), primary_key=True) + repository_path = Column('repository_path', Text) + version = Column('version', Integer) diff --git a/kallithea/lib/dbmigrate/schema/db_2_2_3.py b/kallithea/lib/dbmigrate/schema/db_2_2_3.py new file mode 100755 --- /dev/null +++ b/kallithea/lib/dbmigrate/schema/db_2_2_3.py @@ -0,0 +1,2498 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.db +~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +import os +import time +import logging +import datetime +import traceback +import hashlib +import collections +import functools + +from sqlalchemy import * +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import relationship, joinedload, class_mapper, validates +from sqlalchemy.exc import DatabaseError +from beaker.cache import cache_region, region_invalidate +from webob.exc import HTTPNotFound + +from pylons.i18n.translation import lazy_ugettext as _ + +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset + +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ + safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int, \ + get_clone_url +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache + +from kallithea.model.meta import Base, Session + +URL_SEP = '/' +log = logging.getLogger(__name__) + +from kallithea import DB_PREFIX + +#============================================================================== +# BASE CLASSES +#============================================================================== + +_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest() + + +class BaseModel(object): + """ + Base Model for all classess + """ + + @classmethod + def _get_keys(cls): + """return column names for this model """ + return class_mapper(cls).c.keys() + + def get_dict(self): + """ + return dict with keys and values corresponding + to this model data """ + + d = {} + for k in self._get_keys(): + d[k] = getattr(self, k) + + # also use __json__() if present to get additional fields + _json_attr = getattr(self, '__json__', None) + if _json_attr: + # update with attributes from __json__ + if callable(_json_attr): + _json_attr = _json_attr() + for k, val in _json_attr.iteritems(): + d[k] = val + return d + + def get_appstruct(self): + """return list with keys and values tupples corresponding + to this model data """ + + l = [] + for k in self._get_keys(): + l.append((k, getattr(self, k),)) + return l + + def populate_obj(self, populate_dict): + """populate model with data from given populate_dict""" + + for k in self._get_keys(): + if k in populate_dict: + setattr(self, k, populate_dict[k]) + + @classmethod + def query(cls): + return Session().query(cls) + + @classmethod + def get(cls, id_): + if id_: + return cls.query().get(id_) + + @classmethod + def get_or_404(cls, id_): + try: + id_ = int(id_) + except (TypeError, ValueError): + raise HTTPNotFound + + res = cls.query().get(id_) + if not res: + raise HTTPNotFound + return res + + @classmethod + def getAll(cls): + # deprecated and left for backward compatibility + return cls.get_all() + + @classmethod + def get_all(cls): + return cls.query().all() + + @classmethod + def delete(cls, id_): + obj = cls.query().get(id_) + Session().delete(obj) + + def __repr__(self): + if hasattr(self, '__unicode__'): + # python repr needs to return str + try: + return safe_str(self.__unicode__()) + except UnicodeDecodeError: + pass + return '' % (self.__class__.__name__) + + +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' + __table_args__ = ( + UniqueConstraint('app_settings_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + SETTINGS_TYPES = { + 'str': safe_str, + 'int': safe_int, + 'unicode': safe_unicode, + 'bool': str2bool, + 'list': functools.partial(aslist, sep=',') + } + DEFAULT_UPDATE_URL = '' + + app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + app_settings_name = Column("app_settings_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + _app_settings_value = Column("app_settings_value", String(4096, convert_unicode=False), nullable=True, unique=None, default=None) + _app_settings_type = Column("app_settings_type", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + + def __init__(self, key='', val='', type='unicode'): + self.app_settings_name = key + self.app_settings_value = val + self.app_settings_type = type + + @validates('_app_settings_value') + def validate_settings_value(self, key, val): + assert type(val) == unicode + return val + + @hybrid_property + def app_settings_value(self): + v = self._app_settings_value + _type = self.app_settings_type + converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode'] + return converter(v) + + @app_settings_value.setter + def app_settings_value(self, val): + """ + Setter that will always make sure we use unicode in app_settings_value + + :param val: + """ + self._app_settings_value = safe_unicode(val) + + @hybrid_property + def app_settings_type(self): + return self._app_settings_type + + @app_settings_type.setter + def app_settings_type(self, val): + if val not in self.SETTINGS_TYPES: + raise Exception('type must be one of %s got %s' + % (self.SETTINGS_TYPES.keys(), val)) + self._app_settings_type = val + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % ( + self.__class__.__name__, + self.app_settings_name, self.app_settings_value, self.app_settings_type + ) + + @classmethod + def get_by_name(cls, key): + return cls.query()\ + .filter(cls.app_settings_name == key).scalar() + + @classmethod + def get_by_name_or_create(cls, key, val='', type='unicode'): + res = cls.get_by_name(key) + if not res: + res = cls(key, val, type) + return res + + @classmethod + def create_or_update(cls, key, val=Optional(''), type=Optional('unicode')): + """ + Creates or updates Kallithea setting. If updates is triggered it will only + update parameters that are explicityl set Optional instance will be skipped + + :param key: + :param val: + :param type: + :return: + """ + res = cls.get_by_name(key) + if not res: + val = Optional.extract(val) + type = Optional.extract(type) + res = cls(key, val, type) + else: + res.app_settings_name = key + if not isinstance(val, Optional): + # update if set + res.app_settings_value = val + if not isinstance(type, Optional): + # update if set + res.app_settings_type = type + return res + + @classmethod + def get_app_settings(cls, cache=False): + + ret = cls.query() + + if cache: + ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) + + if not ret: + raise Exception('Could not get application settings !') + settings = {} + for each in ret: + settings[each.app_settings_name] = \ + each.app_settings_value + + return settings + + @classmethod + def get_auth_plugins(cls, cache=False): + auth_plugins = cls.get_by_name("auth_plugins").app_settings_value + return auth_plugins + + @classmethod + def get_auth_settings(cls, cache=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('auth_')).all() + fd = {} + for row in ret: + fd.update({row.app_settings_name: row.app_settings_value}) + + return fd + + @classmethod + def get_default_repo_settings(cls, cache=False, strip_prefix=False): + ret = cls.query()\ + .filter(cls.app_settings_name.startswith('default_')).all() + fd = {} + for row in ret: + key = row.app_settings_name + if strip_prefix: + key = remove_prefix(key, prefix='default_') + fd.update({key: row.app_settings_value}) + + return fd + + @classmethod + def get_server_info(cls): + import pkg_resources + import platform + import kallithea + from kallithea.lib.utils import check_git_version + mods = [(p.project_name, p.version) for p in pkg_resources.working_set] + info = { + 'modules': sorted(mods, key=lambda k: k[0].lower()), + 'py_version': platform.python_version(), + 'platform': safe_unicode(platform.platform()), + 'kallithea_version': kallithea.__version__, + 'git_version': safe_unicode(check_git_version()), + 'git_path': kallithea.CONFIG.get('git_path') + } + return info + + +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' + __table_args__ = ( + UniqueConstraint('ui_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + HOOK_UPDATE = 'changegroup.update' + HOOK_REPO_SIZE = 'changegroup.repo_size' + HOOK_PUSH = 'changegroup.push_logger' + HOOK_PRE_PUSH = 'prechangegroup.pre_push' + HOOK_PULL = 'outgoing.pull_logger' + HOOK_PRE_PULL = 'preoutgoing.pre_pull' + + ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + ui_section = Column("ui_section", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_key = Column("ui_key", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_value = Column("ui_value", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) + + # def __init__(self, section='', key='', value=''): + # self.ui_section = section + # self.ui_key = key + # self.ui_value = value + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.ui_key == key).scalar() + + @classmethod + def get_builtin_hooks(cls): + q = cls.query() + q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + return q.all() + + @classmethod + def get_custom_hooks(cls): + q = cls.query() + q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE, + cls.HOOK_PUSH, cls.HOOK_PRE_PUSH, + cls.HOOK_PULL, cls.HOOK_PRE_PULL])) + q = q.filter(cls.ui_section == 'hooks') + return q.all() + + @classmethod + def get_repos_location(cls): + return cls.get_by_key('/').ui_value + + @classmethod + def create_or_update_hook(cls, key, val): + new_ui = cls.get_by_key(key) or cls() + new_ui.ui_section = 'hooks' + new_ui.ui_active = True + new_ui.ui_key = key + new_ui.ui_value = val + + Session().add(new_ui) + + def __repr__(self): + return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section, + self.ui_key, self.ui_value) + + +class User(Base, BaseModel): + __tablename__ = 'users' + __table_args__ = ( + UniqueConstraint('username'), UniqueConstraint('email'), + Index('u_username_idx', 'username'), + Index('u_email_idx', 'email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + DEFAULT_USER = 'default' + DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}' + + user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + username = Column("username", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + password = Column("password", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + admin = Column("admin", Boolean(), nullable=True, unique=None, default=False) + name = Column("firstname", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + lastname = Column("lastname", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) + extern_type = Column("extern_type", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + extern_name = Column("extern_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + _user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data + + user_log = relationship('UserLog') + user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') + + repositories = relationship('Repository') + user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all') + followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all') + + repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all') + repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all') + + group_member = relationship('UserGroupMember', cascade='all') + + notifications = relationship('UserNotification', cascade='all') + # notifications assigned to this user + user_created_notifications = relationship('Notification', cascade='all') + # comments created by this user + user_comments = relationship('ChangesetComment', cascade='all') + #extra emails for this user + user_emails = relationship('UserEmailMap', cascade='all') + #extra api keys + user_api_keys = relationship('UserApiKeys', cascade='all') + + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + @property + def firstname(self): + # alias for future + return self.name + + @property + def emails(self): + other = UserEmailMap.query().filter(UserEmailMap.user==self).all() + return [self.email] + [x.email for x in other] + + @property + def api_keys(self): + other = UserApiKeys.query().filter(UserApiKeys.user==self).all() + return [self.api_key] + [x.api_key for x in other] + + @property + def ip_addresses(self): + ret = UserIpMap.query().filter(UserIpMap.user == self).all() + return [x.ip_addr for x in ret] + + @property + def username_and_name(self): + return '%s (%s %s)' % (self.username, self.firstname, self.lastname) + + @property + def full_name(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def full_name_or_username(self): + return ('%s %s' % (self.firstname, self.lastname) + if (self.firstname and self.lastname) else self.username) + + @property + def full_contact(self): + return '%s %s <%s>' % (self.firstname, self.lastname, self.email) + + @property + def short_contact(self): + return '%s %s' % (self.firstname, self.lastname) + + @property + def is_admin(self): + return self.admin + + @property + def AuthUser(self): + """ + Returns instance of AuthUser for this user + """ + from kallithea.lib.auth import AuthUser + return AuthUser(user_id=self.user_id, api_key=self.api_key, + username=self.username) + + @hybrid_property + def user_data(self): + if not self._user_data: + return {} + + try: + return json.loads(self._user_data) + except TypeError: + return {} + + @user_data.setter + def user_data(self, val): + try: + self._user_data = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.user_id, self.username) + + @classmethod + def get_by_username(cls, username, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.username.ilike(username)) + else: + q = cls.query().filter(cls.username == username) + + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(username) + ) + ) + return q.scalar() + + @classmethod + def get_by_api_key(cls, api_key, cache=False, fallback=True): + q = cls.query().filter(cls.api_key == api_key) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_api_key_%s" % api_key)) + res = q.scalar() + + if fallback and not res: + #fallback to additional keys + _res = UserApiKeys.query()\ + .filter(UserApiKeys.api_key == api_key)\ + .filter(or_(UserApiKeys.expires == -1, + UserApiKeys.expires >= time.time()))\ + .first() + if _res: + res = _res.user + return res + + @classmethod + def get_by_email(cls, email, case_insensitive=False, cache=False): + if case_insensitive: + q = cls.query().filter(cls.email.ilike(email)) + else: + q = cls.query().filter(cls.email == email) + + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_key_%s" % email)) + + ret = q.scalar() + if ret is None: + q = UserEmailMap.query() + # try fetching in alternate email map + if case_insensitive: + q = q.filter(UserEmailMap.email.ilike(email)) + else: + q = q.filter(UserEmailMap.email == email) + q = q.options(joinedload(UserEmailMap.user)) + if cache: + q = q.options(FromCache("sql_cache_short", + "get_email_map_key_%s" % email)) + ret = getattr(q.scalar(), 'user', None) + + return ret + + @classmethod + def get_from_cs_author(cls, author): + """ + Tries to get User objects out of commit author string + + :param author: + """ + from kallithea.lib.helpers import email, author_name + # Valid email in the attribute passed, see if they're in the system + _email = email(author) + if _email: + user = cls.get_by_email(_email, case_insensitive=True) + if user: + return user + # Maybe we can match by username? + _author = author_name(author) + user = cls.get_by_username(_author, case_insensitive=True) + if user: + return user + + def update_lastlogin(self): + """Update user lastlogin""" + self.last_login = datetime.datetime.now() + Session().add(self) + log.debug('updated user %s lastlogin' % self.username) + + @classmethod + def get_first_admin(cls): + user = User.query().filter(User.admin == True).first() + if user is None: + raise Exception('Missing administrative account!') + return user + + @classmethod + def get_default_user(cls, cache=False): + user = User.get_by_username(User.DEFAULT_USER, cache=cache) + if user is None: + raise Exception('Missing default account!') + return user + + def get_api_data(self): + """ + Common function for generating user related data for API + """ + user = self + data = dict( + user_id=user.user_id, + username=user.username, + firstname=user.name, + lastname=user.lastname, + email=user.email, + emails=user.emails, + api_key=user.api_key, + api_keys=user.api_keys, + active=user.active, + admin=user.admin, + extern_type=user.extern_type, + extern_name=user.extern_name, + last_login=user.last_login, + ip_addresses=user.ip_addresses + ) + return data + + def __json__(self): + data = dict( + full_name=self.full_name, + full_name_or_username=self.full_name_or_username, + short_contact=self.short_contact, + full_contact=self.full_contact + ) + data.update(self.get_api_data()) + return data + + +class UserApiKeys(Base, BaseModel): + __tablename__ = 'user_api_keys' + __table_args__ = ( + Index('uak_api_key_idx', 'api_key'), + Index('uak_api_key_expires_idx', 'api_key', 'expires'), + UniqueConstraint('api_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False), nullable=False, unique=True) + description = Column('description', UnicodeText(1024)) + expires = Column('expires', Float(53), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + user = relationship('User', lazy='joined') + + @property + def expired(self): + if self.expires == -1: + return False + return time.time() > self.expires + + +class UserEmailMap(Base, BaseModel): + __tablename__ = 'user_email_map' + __table_args__ = ( + Index('uem_email_idx', 'email'), + UniqueConstraint('email'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False), nullable=True, unique=False, default=None) + user = relationship('User', lazy='joined') + + @validates('_email') + def validate_email(self, key, email): + # check if this email is not main one + main_email = Session().query(User).filter(User.email == email).scalar() + if main_email is not None: + raise AttributeError('email %s is present is user table' % email) + return email + + @hybrid_property + def email(self): + return self._email + + @email.setter + def email(self, val): + self._email = val.lower() if val else None + + +class UserIpMap(Base, BaseModel): + __tablename__ = 'user_ip_map' + __table_args__ = ( + UniqueConstraint('user_id', 'ip_addr'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + ip_addr = Column("ip_addr", String(255, convert_unicode=False), nullable=True, unique=False, default=None) + active = Column("active", Boolean(), nullable=True, unique=None, default=True) + user = relationship('User', lazy='joined') + + @classmethod + def _get_ip_range(cls, ip_addr): + from kallithea.lib import ipaddr + net = ipaddr.IPNetwork(address=ip_addr) + return [str(net.network), str(net.broadcast)] + + def __json__(self): + return dict( + ip_addr=self.ip_addr, + ip_range=self._get_ip_range(self.ip_addr) + ) + + def __unicode__(self): + return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__, + self.user_id, self.ip_addr) + +class UserLog(Base, BaseModel): + __tablename__ = 'user_logs' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + username = Column("username", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True) + repository_name = Column("repository_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + user_ip = Column("user_ip", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + action = Column("action", UnicodeText(1200000, convert_unicode=False), nullable=True, unique=None, default=None) + action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.repository_name, + self.action) + + @property + def action_as_day(self): + return datetime.date(*self.action_date.timetuple()[:3]) + + user = relationship('User') + repository = relationship('Repository', cascade='') + + +class UserGroup(Base, BaseModel): + __tablename__ = 'users_groups' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_name = Column("users_group_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None) + user_group_description = Column("user_group_description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None) + users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + _group_data = Column("group_data", LargeBinary(), nullable=True) # JSON data + + members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined") + users_group_to_perm = relationship('UserGroupToPerm', cascade='all') + users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all') + user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all') + + user = relationship('User') + + @hybrid_property + def group_data(self): + if not self._group_data: + return {} + + try: + return json.loads(self._group_data) + except TypeError: + return {} + + @group_data.setter + def group_data(self, val): + try: + self._group_data = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, + self.users_group_id, + self.users_group_name) + + @classmethod + def get_by_group_name(cls, group_name, cache=False, + case_insensitive=False): + if case_insensitive: + q = cls.query().filter(cls.users_group_name.ilike(group_name)) + else: + q = cls.query().filter(cls.users_group_name == group_name) + if cache: + q = q.options(FromCache( + "sql_cache_short", + "get_user_%s" % _hash_key(group_name) + ) + ) + return q.scalar() + + @classmethod + def get(cls, user_group_id, cache=False): + user_group = cls.query() + if cache: + user_group = user_group.options(FromCache("sql_cache_short", + "get_users_group_%s" % user_group_id)) + return user_group.get(user_group_id) + + def get_api_data(self, with_members=True): + user_group = self + + data = dict( + users_group_id=user_group.users_group_id, + group_name=user_group.users_group_name, + group_description=user_group.user_group_description, + active=user_group.users_group_active, + owner=user_group.user.username, + ) + if with_members: + members = [] + for user in user_group.members: + user = user.user + members.append(user.get_api_data()) + data['members'] = members + + return data + + +class UserGroupMember(Base, BaseModel): + __tablename__ = 'users_groups_members' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + + user = relationship('User', lazy='joined') + users_group = relationship('UserGroup') + + def __init__(self, gr_id='', u_id=''): + self.users_group_id = gr_id + self.user_id = u_id + + +class RepositoryField(Base, BaseModel): + __tablename__ = 'repositories_fields' + __table_args__ = ( + UniqueConstraint('repository_id', 'field_key'), # no-multi field + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields + + repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + field_key = Column("field_key", String(250, convert_unicode=False)) + field_label = Column("field_label", String(1024, convert_unicode=False), nullable=False) + field_value = Column("field_value", String(10000, convert_unicode=False), nullable=False) + field_desc = Column("field_desc", String(1024, convert_unicode=False), nullable=False) + field_type = Column("field_type", String(256), nullable=False, unique=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repository = relationship('Repository') + + @property + def field_key_prefixed(self): + return 'ex_%s' % self.field_key + + @classmethod + def un_prefix_key(cls, key): + if key.startswith(cls.PREFIX): + return key[len(cls.PREFIX):] + return key + + @classmethod + def get_by_key_name(cls, key, repo): + row = cls.query()\ + .filter(cls.repository == repo)\ + .filter(cls.field_key == key).scalar() + return row + + +class Repository(Base, BaseModel): + __tablename__ = 'repositories' + __table_args__ = ( + UniqueConstraint('repo_name'), + Index('r_repo_name_idx', 'repo_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}' + DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}' + + STATE_CREATED = 'repo_state_created' + STATE_PENDING = 'repo_state_pending' + STATE_ERROR = 'repo_state_error' + + repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repo_name = Column("repo_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None) + repo_state = Column("repo_state", String(255), nullable=True) + + clone_uri = Column("clone_uri", String(255, convert_unicode=False), nullable=True, unique=False, default=None) + repo_type = Column("repo_type", String(255, convert_unicode=False), nullable=False, unique=False, default=None) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + private = Column("private", Boolean(), nullable=True, unique=None, default=None) + enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True) + enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True) + description = Column("description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + _landing_revision = Column("landing_revision", String(255, convert_unicode=False), nullable=False, unique=False, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + _locked = Column("locked", String(255, convert_unicode=False), nullable=True, unique=False, default=None) + _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data + + fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) + + user = relationship('User') + fork = relationship('Repository', remote_side=repo_id) + group = relationship('RepoGroup') + repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all') + stats = relationship('Statistics', cascade='all', uselist=False) + + followers = relationship('UserFollowing', + primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', + cascade='all') + extra_fields = relationship('RepositoryField', + cascade="all, delete, delete-orphan") + + logs = relationship('UserLog') + comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan") + + pull_requests_org = relationship('PullRequest', + primaryjoin='PullRequest.org_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + pull_requests_other = relationship('PullRequest', + primaryjoin='PullRequest.other_repo_id==Repository.repo_id', + cascade="all, delete, delete-orphan") + + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, + safe_unicode(self.repo_name)) + + @hybrid_property + def landing_rev(self): + # always should return [rev_type, rev] + if self._landing_revision: + _rev_info = self._landing_revision.split(':') + if len(_rev_info) < 2: + _rev_info.insert(0, 'rev') + return [_rev_info[0], _rev_info[1]] + return [None, None] + + @landing_rev.setter + def landing_rev(self, val): + if ':' not in val: + raise ValueError('value must be delimited with `:` and consist ' + 'of :, got %s instead' % val) + self._landing_revision = val + + @hybrid_property + def locked(self): + # always should return [user_id, timelocked] + if self._locked: + _lock_info = self._locked.split(':') + return int(_lock_info[0]), _lock_info[1] + return [None, None] + + @locked.setter + def locked(self, val): + if val and isinstance(val, (list, tuple)): + self._locked = ':'.join(map(str, val)) + else: + self._locked = None + + @hybrid_property + def changeset_cache(self): + from kallithea.lib.vcs.backends.base import EmptyChangeset + dummy = EmptyChangeset().__json__() + if not self._changeset_cache: + return dummy + try: + return json.loads(self._changeset_cache) + except TypeError: + return dummy + + @changeset_cache.setter + def changeset_cache(self, val): + try: + self._changeset_cache = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def normalize_repo_name(cls, repo_name): + """ + Normalizes os specific repo_name to the format internally stored inside + dabatabase using URL_SEP + + :param cls: + :param repo_name: + """ + return cls.url_sep().join(repo_name.split(os.sep)) + + @classmethod + def get_by_repo_name(cls, repo_name): + q = Session().query(cls).filter(cls.repo_name == repo_name) + q = q.options(joinedload(Repository.fork))\ + .options(joinedload(Repository.user))\ + .options(joinedload(Repository.group)) + return q.scalar() + + @classmethod + def get_by_full_path(cls, repo_full_path): + repo_name = repo_full_path.split(cls.base_path(), 1)[-1] + repo_name = cls.normalize_repo_name(repo_name) + return cls.get_by_repo_name(repo_name.strip(URL_SEP)) + + @classmethod + def get_repo_forks(cls, repo_id): + return cls.query().filter(Repository.fork_id == repo_id) + + @classmethod + def base_path(cls): + """ + Returns base path when all repos are stored + + :param cls: + """ + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def forks(self): + """ + Return forks of this repo + """ + return Repository.get_repo_forks(self.repo_id) + + @property + def parent(self): + """ + Returns fork parent + """ + return self.fork + + @property + def just_name(self): + return self.repo_name.split(Repository.url_sep())[-1] + + @property + def groups_with_parents(self): + groups = [] + if self.group is None: + return groups + + cur_gr = self.group + groups.insert(0, cur_gr) + while 1: + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + groups.insert(0, gr) + + return groups + + @property + def groups_and_repo(self): + return self.groups_with_parents, self.just_name, self.repo_name + + @LazyProperty + def repo_path(self): + """ + Returns base full path for that repository means where it actually + exists on a filesystem + """ + q = Session().query(Ui).filter(Ui.ui_key == + Repository.url_sep()) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return q.one().ui_value + + @property + def repo_full_path(self): + p = [self.repo_path] + # we need to split the name by / since this is how we store the + # names in the database, but that eventually needs to be converted + # into a valid system path + p += self.repo_name.split(Repository.url_sep()) + return os.path.join(*map(safe_unicode, p)) + + @property + def cache_keys(self): + """ + Returns associated cache keys for that repo + """ + return CacheInvalidation.query()\ + .filter(CacheInvalidation.cache_args == self.repo_name)\ + .order_by(CacheInvalidation.cache_key)\ + .all() + + def get_new_name(self, repo_name): + """ + returns new full repository name based on assigned group and new new + + :param group_name: + """ + path_prefix = self.group.full_path_splitted if self.group else [] + return Repository.url_sep().join(path_prefix + [repo_name]) + + @property + def _ui(self): + """ + Creates an db based ui object for this repository + """ + from kallithea.lib.utils import make_ui + return make_ui('db', clear_session=False) + + @classmethod + def is_valid(cls, repo_name): + """ + returns True if given repo name is a valid filesystem repository + + :param cls: + :param repo_name: + """ + from kallithea.lib.utils import is_valid_repo + + return is_valid_repo(repo_name, cls.base_path()) + + def get_api_data(self): + """ + Common function for generating repo api data + + """ + repo = self + data = dict( + repo_id=repo.repo_id, + repo_name=repo.repo_name, + repo_type=repo.repo_type, + clone_uri=repo.clone_uri, + private=repo.private, + created_on=repo.created_on, + description=repo.description, + landing_rev=repo.landing_rev, + owner=repo.user.username, + fork_of=repo.fork.repo_name if repo.fork else None, + enable_statistics=repo.enable_statistics, + enable_locking=repo.enable_locking, + enable_downloads=repo.enable_downloads, + last_changeset=repo.changeset_cache, + locked_by=User.get(self.locked[0]).get_api_data() \ + if self.locked[0] else None, + locked_date=time_to_datetime(self.locked[1]) \ + if self.locked[1] else None + ) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) + if repository_fields: + for f in self.extra_fields: + data[f.field_key_prefixed] = f.field_value + + return data + + @classmethod + def lock(cls, repo, user_id, lock_time=None): + if not lock_time: + lock_time = time.time() + repo.locked = [user_id, lock_time] + Session().add(repo) + Session().commit() + + @classmethod + def unlock(cls, repo): + repo.locked = None + Session().add(repo) + Session().commit() + + @classmethod + def getlock(cls, repo): + return repo.locked + + @property + def last_db_change(self): + return self.updated_on + + def clone_url(self, **override): + from pylons import url + qualified_home_url = url('home', qualified=True) + + uri_tmpl = None + if 'with_id' in override: + uri_tmpl = self.DEFAULT_CLONE_URI_ID + del override['with_id'] + + if 'uri_tmpl' in override: + uri_tmpl = override['uri_tmpl'] + del override['uri_tmpl'] + + # we didn't override our tmpl from **overrides + if not uri_tmpl: + uri_tmpl = self.DEFAULT_CLONE_URI + try: + from pylons import tmpl_context as c + uri_tmpl = c.clone_uri_tmpl + except Exception: + # in any case if we call this outside of request context, + # ie, not having tmpl_context set up + pass + + return get_clone_url(uri_tmpl=uri_tmpl, + qualifed_home_url=qualified_home_url, + repo_name=self.repo_name, + repo_id=self.repo_id, **override) + + def set_state(self, state): + self.repo_state = state + Session().add(self) + #========================================================================== + # SCM PROPERTIES + #========================================================================== + + def get_changeset(self, rev=None): + return get_changeset_safe(self.scm_instance, rev) + + def get_landing_changeset(self): + """ + Returns landing changeset, or if that doesn't exist returns the tip + """ + _rev_type, _rev = self.landing_rev + cs = self.get_changeset(_rev) + if isinstance(cs, EmptyChangeset): + return self.get_changeset() + return cs + + def update_changeset_cache(self, cs_cache=None): + """ + Update cache of last changeset for repository, keys should be:: + + short_id + raw_id + revision + message + date + author + + :param cs_cache: + """ + from kallithea.lib.vcs.backends.base import BaseChangeset + if cs_cache is None: + cs_cache = EmptyChangeset() + # use no-cache version here + scm_repo = self.scm_instance_no_cache() + if scm_repo: + cs_cache = scm_repo.get_changeset() + + if isinstance(cs_cache, BaseChangeset): + cs_cache = cs_cache.__json__() + + if (cs_cache != self.changeset_cache or not self.changeset_cache): + _default = datetime.datetime.fromtimestamp(0) + last_change = cs_cache.get('date') or _default + log.debug('updated repo %s with new cs cache %s' + % (self.repo_name, cs_cache)) + self.updated_on = last_change + self.changeset_cache = cs_cache + Session().add(self) + Session().commit() + else: + log.debug('Skipping repo:%s already with latest changes' + % self.repo_name) + + @property + def tip(self): + return self.get_changeset('tip') + + @property + def author(self): + return self.tip.author + + @property + def last_change(self): + return self.scm_instance.last_change + + def get_comments(self, revisions=None): + """ + Returns comments for this repository grouped by revisions + + :param revisions: filter query by revisions only + """ + cmts = ChangesetComment.query()\ + .filter(ChangesetComment.repo == self) + if revisions: + cmts = cmts.filter(ChangesetComment.revision.in_(revisions)) + grouped = collections.defaultdict(list) + for cmt in cmts.all(): + grouped[cmt.revision].append(cmt) + return grouped + + def statuses(self, revisions=None): + """ + Returns statuses for this repository + + :param revisions: list of revisions to get statuses for + """ + + statuses = ChangesetStatus.query()\ + .filter(ChangesetStatus.repo == self)\ + .filter(ChangesetStatus.version == 0) + if revisions: + statuses = statuses.filter(ChangesetStatus.revision.in_(revisions)) + grouped = {} + + #maybe we have open new pullrequest without a status ? + stat = ChangesetStatus.STATUS_UNDER_REVIEW + status_lbl = ChangesetStatus.get_status_lbl(stat) + for pr in PullRequest.query().filter(PullRequest.org_repo == self).all(): + for rev in pr.revisions: + pr_id = pr.pull_request_id + pr_repo = pr.other_repo.repo_name + grouped[rev] = [stat, status_lbl, pr_id, pr_repo] + + for stat in statuses.all(): + pr_id = pr_repo = None + if stat.pull_request: + pr_id = stat.pull_request.pull_request_id + pr_repo = stat.pull_request.other_repo.repo_name + grouped[stat.revision] = [str(stat.status), stat.status_lbl, + pr_id, pr_repo] + return grouped + + def _repo_size(self): + from kallithea.lib import helpers as h + log.debug('calculating repository size...') + return h.format_byte_size(self.scm_instance.size) + + #========================================================================== + # SCM CACHE INSTANCE + #========================================================================== + + def set_invalidate(self): + """ + Mark caches of this repo as invalid. + """ + CacheInvalidation.set_invalidate(self.repo_name) + + def scm_instance_no_cache(self): + return self.__get_instance() + + @property + def scm_instance(self): + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) + if full_cache: + return self.scm_instance_cached() + return self.__get_instance() + + def scm_instance_cached(self, valid_cache_keys=None): + @cache_region('long_term') + def _c(repo_name): + return self.__get_instance() + rn = self.repo_name + + valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys) + if not valid: + log.debug('Cache for %s invalidated, getting new object' % (rn)) + region_invalidate(_c, None, rn) + else: + log.debug('Getting obj for %s from cache' % (rn)) + return _c(rn) + + def __get_instance(self): + repo_full_path = self.repo_full_path + try: + alias = get_scm(repo_full_path)[0] + log.debug('Creating instance of %s repository from %s' + % (alias, repo_full_path)) + backend = get_backend(alias) + except VCSError: + log.error(traceback.format_exc()) + log.error('Perhaps this repository is in db and not in ' + 'filesystem run rescan repositories with ' + '"destroy old data " option from admin panel') + return + + if alias == 'hg': + + repo = backend(safe_str(repo_full_path), create=False, + baseui=self._ui) + # skip hidden web repository + if repo._get_hidden(): + return + else: + repo = backend(repo_full_path, create=False) + + return repo + + def __json__(self): + return dict(landing_rev = self.landing_rev) + +class RepoGroup(Base, BaseModel): + __tablename__ = 'groups' + __table_args__ = ( + UniqueConstraint('group_name', 'group_parent_id'), + CheckConstraint('group_id != group_parent_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + __mapper_args__ = {'order_by': 'group_name'} + + SEP = ' » ' + + group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + group_name = Column("group_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None) + group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) + group_description = Column("group_description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None) + enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id') + users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') + parent_group = relationship('RepoGroup', remote_side=group_id) + user = relationship('User') + + def __init__(self, group_name='', parent_group=None): + self.group_name = group_name + self.parent_group = parent_group + + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id, + self.group_name) + + @classmethod + def _generate_choice(cls, repo_group): + from webhelpers.html import literal as _literal + _name = lambda k: _literal(cls.SEP.join(k)) + return repo_group.group_id, _name(repo_group.full_path_splitted) + + @classmethod + def groups_choices(cls, groups=None, show_empty_group=True): + if not groups: + groups = cls.query().all() + + repo_groups = [] + if show_empty_group: + repo_groups = [('-1', u'-- %s --' % _('top level'))] + + repo_groups.extend([cls._generate_choice(x) for x in groups]) + + repo_groups = sorted(repo_groups, key=lambda t: t[1].split(cls.SEP)[0]) + return repo_groups + + @classmethod + def url_sep(cls): + return URL_SEP + + @classmethod + def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): + if case_insensitive: + gr = cls.query()\ + .filter(cls.group_name.ilike(group_name)) + else: + gr = cls.query()\ + .filter(cls.group_name == group_name) + if cache: + gr = gr.options(FromCache( + "sql_cache_short", + "get_group_%s" % _hash_key(group_name) + ) + ) + return gr.scalar() + + @property + def parents(self): + parents_recursion_limit = 5 + groups = [] + if self.parent_group is None: + return groups + cur_gr = self.parent_group + groups.insert(0, cur_gr) + cnt = 0 + while 1: + cnt += 1 + gr = getattr(cur_gr, 'parent_group', None) + cur_gr = cur_gr.parent_group + if gr is None: + break + if cnt == parents_recursion_limit: + # this will prevent accidental infinit loops + log.error('group nested more than %s' % + parents_recursion_limit) + break + + groups.insert(0, gr) + return groups + + @property + def children(self): + return RepoGroup.query().filter(RepoGroup.parent_group == self) + + @property + def name(self): + return self.group_name.split(RepoGroup.url_sep())[-1] + + @property + def full_path(self): + return self.group_name + + @property + def full_path_splitted(self): + return self.group_name.split(RepoGroup.url_sep()) + + @property + def repositories(self): + return Repository.query()\ + .filter(Repository.group == self)\ + .order_by(Repository.repo_name) + + @property + def repositories_recursive_count(self): + cnt = self.repositories.count() + + def children_count(group): + cnt = 0 + for child in group.children: + cnt += child.repositories.count() + cnt += children_count(child) + return cnt + + return cnt + children_count(self) + + def _recursive_objects(self, include_repos=True): + all_ = [] + + def _get_members(root_gr): + if include_repos: + for r in root_gr.repositories: + all_.append(r) + childs = root_gr.children.all() + if childs: + for gr in childs: + all_.append(gr) + _get_members(gr) + + _get_members(self) + return [self] + all_ + + def recursive_groups_and_repos(self): + """ + Recursive return all groups, with repositories in those groups + """ + return self._recursive_objects() + + def recursive_groups(self): + """ + Returns all children groups for this group including children of children + """ + return self._recursive_objects(include_repos=False) + + def get_new_name(self, group_name): + """ + returns new full group name based on parent and new name + + :param group_name: + """ + path_prefix = (self.parent_group.full_path_splitted if + self.parent_group else []) + return RepoGroup.url_sep().join(path_prefix + [group_name]) + + def get_api_data(self): + """ + Common function for generating api data + + """ + group = self + data = dict( + group_id=group.group_id, + group_name=group.group_name, + group_description=group.group_description, + parent_group=group.parent_group.group_name if group.parent_group else None, + repositories=[x.repo_name for x in group.repositories], + owner=group.user.username + ) + return data + + +class Permission(Base, BaseModel): + __tablename__ = 'permissions' + __table_args__ = ( + Index('p_perm_name_idx', 'permission_name'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + PERMS = [ + ('hg.admin', _('Kallithea Administrator')), + + ('repository.none', _('Repository no access')), + ('repository.read', _('Repository read access')), + ('repository.write', _('Repository write access')), + ('repository.admin', _('Repository admin access')), + + ('group.none', _('Repository group no access')), + ('group.read', _('Repository group read access')), + ('group.write', _('Repository group write access')), + ('group.admin', _('Repository group admin access')), + + ('usergroup.none', _('User group no access')), + ('usergroup.read', _('User group read access')), + ('usergroup.write', _('User group write access')), + ('usergroup.admin', _('User group admin access')), + + ('hg.repogroup.create.false', _('Repository Group creation disabled')), + ('hg.repogroup.create.true', _('Repository Group creation enabled')), + + ('hg.usergroup.create.false', _('User Group creation disabled')), + ('hg.usergroup.create.true', _('User Group creation enabled')), + + ('hg.create.none', _('Repository creation disabled')), + ('hg.create.repository', _('Repository creation enabled')), + ('hg.create.write_on_repogroup.true', _('Repository creation enabled with write permission to a repository group')), + ('hg.create.write_on_repogroup.false', _('Repository creation disabled with write permission to a repository group')), + + ('hg.fork.none', _('Repository forking disabled')), + ('hg.fork.repository', _('Repository forking enabled')), + + ('hg.register.none', _('Registration disabled')), + ('hg.register.manual_activate', _('User Registration with manual account activation')), + ('hg.register.auto_activate', _('User Registration with automatic account activation')), + + ('hg.extern_activate.manual', _('Manual activation of external account')), + ('hg.extern_activate.auto', _('Automatic activation of external account')), + + ] + + #definition of system default permissions for DEFAULT user + DEFAULT_USER_PERMISSIONS = [ + 'repository.read', + 'group.read', + 'usergroup.read', + 'hg.create.repository', + 'hg.create.write_on_repogroup.true', + 'hg.fork.repository', + 'hg.register.manual_activate', + 'hg.extern_activate.auto', + ] + + # defines which permissions are more important higher the more important + # Weight defines which permissions are more important. + # The higher number the more important. + PERM_WEIGHTS = { + 'repository.none': 0, + 'repository.read': 1, + 'repository.write': 3, + 'repository.admin': 4, + + 'group.none': 0, + 'group.read': 1, + 'group.write': 3, + 'group.admin': 4, + + 'usergroup.none': 0, + 'usergroup.read': 1, + 'usergroup.write': 3, + 'usergroup.admin': 4, + 'hg.repogroup.create.false': 0, + 'hg.repogroup.create.true': 1, + + 'hg.usergroup.create.false': 0, + 'hg.usergroup.create.true': 1, + + 'hg.fork.none': 0, + 'hg.fork.repository': 1, + 'hg.create.none': 0, + 'hg.create.repository': 1 + } + + permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + permission_name = Column("permission_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + permission_longname = Column("permission_longname", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, self.permission_id, self.permission_name + ) + + @classmethod + def get_by_key(cls, key): + return cls.query().filter(cls.permission_name == key).scalar() + + @classmethod + def get_default_perms(cls, default_user_id): + q = Session().query(UserRepoToPerm, Repository, cls)\ + .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ + .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_group_perms(cls, default_user_id): + q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\ + .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\ + .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserRepoGroupToPerm.user_id == default_user_id) + + return q.all() + + @classmethod + def get_default_user_group_perms(cls, default_user_id): + q = Session().query(UserUserGroupToPerm, UserGroup, cls)\ + .join((UserGroup, UserUserGroupToPerm.user_group_id == UserGroup.users_group_id))\ + .join((cls, UserUserGroupToPerm.permission_id == cls.permission_id))\ + .filter(UserUserGroupToPerm.user_id == default_user_id) + + return q.all() + + +class UserRepoToPerm(Base, BaseModel): + __tablename__ = 'repo_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'repository_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + repository = relationship('Repository') + permission = relationship('Permission') + + @classmethod + def create(cls, user, repository, permission): + n = cls() + n.user = user + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.repository) + + +class UserUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'user_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + user_group = relationship('UserGroup') + permission = relationship('Permission') + + @classmethod + def create(cls, user, user_group, permission): + n = cls() + n.user = user + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.user_group) + + +class UserToPerm(Base, BaseModel): + __tablename__ = 'user_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + permission = relationship('Permission', lazy='joined') + + def __unicode__(self): + return u'<%s => %s >' % (self.user, self.permission) + + +class UserGroupRepoToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_to_perm' + __table_args__ = ( + UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + repository = relationship('Repository') + + @classmethod + def create(cls, users_group, repository, permission): + n = cls() + n.users_group = users_group + n.repository = repository + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.users_group, self.repository) + + +class UserGroupUserGroupToPerm(Base, BaseModel): + __tablename__ = 'user_group_user_group_to_perm' + __table_args__ = ( + UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'), + CheckConstraint('target_user_group_id != user_group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + + target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id') + user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id') + permission = relationship('Permission') + + @classmethod + def create(cls, target_user_group, user_group, permission): + n = cls() + n.target_user_group = target_user_group + n.user_group = user_group + n.permission = permission + Session().add(n) + return n + + def __unicode__(self): + return u' %s >' % (self.target_user_group, self.user_group) + + +class UserGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'permission_id',), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + + +class UserRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'user_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('user_id', 'group_id', 'permission_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + user = relationship('User') + group = relationship('RepoGroup') + permission = relationship('Permission') + + @classmethod + def create(cls, user, repository_group, permission): + n = cls() + n.user = user + n.group = repository_group + n.permission = permission + Session().add(n) + return n + + +class UserGroupRepoGroupToPerm(Base, BaseModel): + __tablename__ = 'users_group_repo_group_to_perm' + __table_args__ = ( + UniqueConstraint('users_group_id', 'group_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UserGroup') + permission = relationship('Permission') + group = relationship('RepoGroup') + + @classmethod + def create(cls, user_group, repository_group, permission): + n = cls() + n.users_group = user_group + n.group = repository_group + n.permission = permission + Session().add(n) + return n + + +class Statistics(Base, BaseModel): + __tablename__ = 'statistics' + __table_args__ = ( + UniqueConstraint('repository_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) + stat_on_revision = Column("stat_on_revision", Integer(), nullable=False) + commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data + commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data + languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data + + repository = relationship('Repository', single_parent=True) + + +class UserFollowing(Base, BaseModel): + __tablename__ = 'user_followings' + __table_args__ = ( + UniqueConstraint('user_id', 'follows_repository_id'), + UniqueConstraint('user_id', 'follows_user_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + + user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None) + follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + + user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') + + follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') + follows_repository = relationship('Repository', order_by='Repository.repo_name') + + @classmethod + def get_repo_followers(cls, repo_id): + return cls.query().filter(cls.follows_repo_id == repo_id) + + +class CacheInvalidation(Base, BaseModel): + __tablename__ = 'cache_invalidation' + __table_args__ = ( + UniqueConstraint('cache_key'), + Index('key_idx', 'cache_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + # cache_id, not used + cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + # cache_key as created by _get_cache_key + cache_key = Column("cache_key", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + # cache_args is a repo_name + cache_args = Column("cache_args", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + # instance sets cache_active True when it is caching, + # other instances set cache_active to False to indicate that this cache is invalid + cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False) + + def __init__(self, cache_key, repo_name=''): + self.cache_key = cache_key + self.cache_args = repo_name + self.cache_active = False + + def __unicode__(self): + return u"<%s('%s:%s[%s]')>" % (self.__class__.__name__, + self.cache_id, self.cache_key, self.cache_active) + + def _cache_key_partition(self): + prefix, repo_name, suffix = self.cache_key.partition(self.cache_args) + return prefix, repo_name, suffix + + def get_prefix(self): + """ + get prefix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[0] + + def get_suffix(self): + """ + get suffix that might have been used in _get_cache_key to + generate self.cache_key. Only used for informational purposes + in repo_edit.html. + """ + # prefix, repo_name, suffix + return self._cache_key_partition()[2] + + @classmethod + def clear_cache(cls): + """ + Delete all cache keys from database. + Should only be run when all instances are down and all entries thus stale. + """ + cls.query().delete() + Session().commit() + + @classmethod + def _get_cache_key(cls, key): + """ + Wrapper for generating a unique cache key for this instance and "key". + key must / will start with a repo_name which will be stored in .cache_args . + """ + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') + return "%s%s" % (prefix, key) + + @classmethod + def set_invalidate(cls, repo_name, delete=False): + """ + Mark all caches of a repo as invalid in the database. + """ + inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all() + log.debug('for repo %s got %s invalidation objects' + % (safe_str(repo_name), inv_objs)) + try: + for inv_obj in inv_objs: + log.debug('marking %s key for invalidation based on repo_name=%s' + % (inv_obj, safe_str(repo_name))) + if delete: + Session().delete(inv_obj) + else: + inv_obj.cache_active = False + Session().add(inv_obj) + Session().commit() + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + + @classmethod + def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None): + """ + Mark this cache key as active and currently cached. + Return True if the existing cache registration still was valid. + Return False to indicate that it had been invalidated and caches should be refreshed. + """ + + key = (repo_name + '_' + kind) if kind else repo_name + cache_key = cls._get_cache_key(key) + + if valid_cache_keys and cache_key in valid_cache_keys: + return True + + try: + inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar() + if not inv_obj: + inv_obj = CacheInvalidation(cache_key, repo_name) + was_valid = inv_obj.cache_active + inv_obj.cache_active = True + Session().add(inv_obj) + Session().commit() + return was_valid + except Exception: + log.error(traceback.format_exc()) + Session().rollback() + return False + + @classmethod + def get_valid_cache_keys(cls): + """ + Return opaque object with information of which caches still are valid + and can be used without checking for invalidation. + """ + return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all()) + + +class ChangesetComment(Base, BaseModel): + __tablename__ = 'changeset_comments' + __table_args__ = ( + Index('cc_revision_idx', 'revision'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + revision = Column('revision', String(40), nullable=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + line_no = Column('line_no', Unicode(10), nullable=True) + hl_lines = Column('hl_lines', Unicode(512), nullable=True) + f_path = Column('f_path', Unicode(1000), nullable=True) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) + text = Column('text', UnicodeText(25000), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan") + pull_request = relationship('PullRequest', lazy='joined') + + @classmethod + def get_users(cls, revision=None, pull_request_id=None): + """ + Returns user associated with this ChangesetComment. ie those + who actually commented + + :param cls: + :param revision: + """ + q = Session().query(User)\ + .join(ChangesetComment.author) + if revision: + q = q.filter(cls.revision == revision) + elif pull_request_id: + q = q.filter(cls.pull_request_id == pull_request_id) + return q.all() + + +class ChangesetStatus(Base, BaseModel): + __tablename__ = 'changeset_statuses' + __table_args__ = ( + Index('cs_revision_idx', 'revision'), + Index('cs_version_idx', 'version'), + UniqueConstraint('repo_id', 'revision', 'version'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed' + STATUS_APPROVED = 'approved' + STATUS_REJECTED = 'rejected' + STATUS_UNDER_REVIEW = 'under_review' + + STATUSES = [ + (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default + (STATUS_APPROVED, _("Approved")), + (STATUS_REJECTED, _("Rejected")), + (STATUS_UNDER_REVIEW, _("Under Review")), + ] + + changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + revision = Column('revision', String(40), nullable=False) + status = Column('status', String(128), nullable=False, default=DEFAULT) + changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id')) + modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now) + version = Column('version', Integer(), nullable=False, default=0) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) + + author = relationship('User', lazy='joined') + repo = relationship('Repository') + comment = relationship('ChangesetComment', lazy='joined') + pull_request = relationship('PullRequest', lazy='joined') + + def __unicode__(self): + return u"<%s('%s:%s')>" % ( + self.__class__.__name__, + self.status, self.author + ) + + @classmethod + def get_status_lbl(cls, value): + return dict(cls.STATUSES).get(value) + + @property + def status_lbl(self): + return ChangesetStatus.get_status_lbl(self.status) + + +class PullRequest(Base, BaseModel): + __tablename__ = 'pull_requests' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + # values for .status + STATUS_NEW = u'new' + STATUS_OPEN = u'open' + STATUS_CLOSED = u'closed' + + pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) + title = Column('title', Unicode(256), nullable=True) + description = Column('description', UnicodeText(10240), nullable=True) + status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW) # only for closedness, not approve/reject/etc + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max + org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + org_ref = Column('org_ref', Unicode(256), nullable=False) + other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + other_ref = Column('other_ref', Unicode(256), nullable=False) + + @hybrid_property + def revisions(self): + return self._revisions.split(':') + + @revisions.setter + def revisions(self, val): + self._revisions = ':'.join(val) + + @property + def org_ref_parts(self): + return self.org_ref.split(':') + + @property + def other_ref_parts(self): + return self.other_ref.split(':') + + author = relationship('User', lazy='joined') + reviewers = relationship('PullRequestReviewers', + cascade="all, delete, delete-orphan") + org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') + other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id') + statuses = relationship('ChangesetStatus') + comments = relationship('ChangesetComment', + cascade="all, delete, delete-orphan") + + def is_closed(self): + return self.status == self.STATUS_CLOSED + + @property + def last_review_status(self): + return self.statuses[-1].status if self.statuses else '' + + def __json__(self): + return dict( + revisions=self.revisions + ) + + +class PullRequestReviewers(Base, BaseModel): + __tablename__ = 'pull_request_reviewers' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + def __init__(self, user=None, pull_request=None): + self.user = user + self.pull_request = pull_request + + pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True) + pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True) + + user = relationship('User') + pull_request = relationship('PullRequest') + + +class Notification(Base, BaseModel): + __tablename__ = 'notifications' + __table_args__ = ( + Index('notification_type_idx', 'type'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + + TYPE_CHANGESET_COMMENT = u'cs_comment' + TYPE_MESSAGE = u'message' + TYPE_MENTION = u'mention' + TYPE_REGISTRATION = u'registration' + TYPE_PULL_REQUEST = u'pull_request' + TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' + + notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) + subject = Column('subject', Unicode(512), nullable=True) + body = Column('body', UnicodeText(50000), nullable=True) + created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + type_ = Column('type', Unicode(256)) + + created_by_user = relationship('User') + notifications_to_users = relationship('UserNotification', lazy='joined', + cascade="all, delete, delete-orphan") + + @property + def recipients(self): + return [x.user for x in UserNotification.query()\ + .filter(UserNotification.notification == self)\ + .order_by(UserNotification.user_id.asc()).all()] + + @classmethod + def create(cls, created_by, subject, body, recipients, type_=None): + if type_ is None: + type_ = Notification.TYPE_MESSAGE + + notification = cls() + notification.created_by_user = created_by + notification.subject = subject + notification.body = body + notification.type_ = type_ + notification.created_on = datetime.datetime.now() + + for u in recipients: + assoc = UserNotification() + assoc.notification = notification + u.notifications.append(assoc) + Session().add(notification) + return notification + + @property + def description(self): + from kallithea.model.notification import NotificationModel + return NotificationModel().make_description(self) + + +class UserNotification(Base, BaseModel): + __tablename__ = 'user_to_notification' + __table_args__ = ( + UniqueConstraint('user_id', 'notification_id'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True) + notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True) + read = Column('read', Boolean, default=False) + sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None) + + user = relationship('User', lazy="joined") + notification = relationship('Notification', lazy="joined", + order_by=lambda: Notification.created_on.desc(),) + + def mark_as_read(self): + self.read = True + Session().add(self) + + +class Gist(Base, BaseModel): + __tablename__ = 'gists' + __table_args__ = ( + Index('g_gist_access_id_idx', 'gist_access_id'), + Index('g_created_on_idx', 'created_on'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + GIST_PUBLIC = u'public' + GIST_PRIVATE = u'private' + DEFAULT_FILENAME = u'gistfile1.txt' + + gist_id = Column('gist_id', Integer(), primary_key=True) + gist_access_id = Column('gist_access_id', Unicode(250)) + gist_description = Column('gist_description', UnicodeText(1024)) + gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True) + gist_expires = Column('gist_expires', Float(53), nullable=False) + gist_type = Column('gist_type', Unicode(128), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + owner = relationship('User') + + def __repr__(self): + return '' % (self.gist_type, self.gist_access_id) + + @classmethod + def get_or_404(cls, id_): + res = cls.query().filter(cls.gist_access_id == id_).scalar() + if not res: + raise HTTPNotFound + return res + + @classmethod + def get_by_access_id(cls, gist_access_id): + return cls.query().filter(cls.gist_access_id == gist_access_id).scalar() + + def gist_url(self): + import kallithea + alias_url = kallithea.CONFIG.get('gist_alias_url') + if alias_url: + return alias_url.replace('{gistid}', self.gist_access_id) + + from pylons import url + return url('gist', gist_id=self.gist_access_id, qualified=True) + + @classmethod + def base_path(cls): + """ + Returns base path when all gists are stored + + :param cls: + """ + from kallithea.model.gist import GIST_STORE_LOC + q = Session().query(Ui)\ + .filter(Ui.ui_key == URL_SEP) + q = q.options(FromCache("sql_cache_short", "repository_repo_path")) + return os.path.join(q.one().ui_value, GIST_STORE_LOC) + + def get_api_data(self): + """ + Common function for generating gist related data for API + """ + gist = self + data = dict( + gist_id=gist.gist_id, + type=gist.gist_type, + access_id=gist.gist_access_id, + description=gist.gist_description, + url=gist.gist_url(), + expires=gist.gist_expires, + created_on=gist.created_on, + ) + return data + + def __json__(self): + data = dict( + ) + data.update(self.get_api_data()) + return data + ## SCM functions + + @property + def scm_instance(self): + from kallithea.lib.vcs import get_repo + base_path = self.base_path() + return get_repo(os.path.join(*map(safe_str, + [base_path, self.gist_access_id]))) + + +class DbMigrateVersion(Base, BaseModel): + __tablename__ = 'db_migrate_version' + __table_args__ = ( + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, + ) + repository_id = Column('repository_id', String(250), primary_key=True) + repository_path = Column('repository_path', Text) + version = Column('version', Integer) diff --git a/rhodecode/lib/dbmigrate/versions/001_initial_release.py b/kallithea/lib/dbmigrate/versions/001_initial_release.py rename from rhodecode/lib/dbmigrate/versions/001_initial_release.py rename to kallithea/lib/dbmigrate/versions/001_initial_release.py --- a/rhodecode/lib/dbmigrate/versions/001_initial_release.py +++ b/kallithea/lib/dbmigrate/versions/001_initial_release.py @@ -8,14 +8,16 @@ from sqlalchemy import * from sqlalchemy.exc import DatabaseError from sqlalchemy.orm import relation, backref, class_mapper from sqlalchemy.orm.session import Session -from rhodecode.model.meta import Base +from kallithea.model.meta import Base -from rhodecode.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate import * + +from kallithea import DB_PREFIX log = logging.getLogger(__name__) -class RhodeCodeSetting(Base): - __tablename__ = 'rhodecode_settings' +class Setting(Base): + __tablename__ = DB_PREFIX + 'settings' __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True}) app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) app_settings_name = Column("app_settings_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) @@ -26,11 +28,11 @@ class RhodeCodeSetting(Base): self.app_settings_value = v def __repr__(self): - return "" % (self.app_settings_name, + return "" % (self.app_settings_name, self.app_settings_value) -class RhodeCodeUi(Base): - __tablename__ = 'rhodecode_ui' +class Ui(Base): + __tablename__ = DB_PREFIX + 'ui' __table_args__ = {'useexisting':True} ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) ui_section = Column("ui_section", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) diff --git a/rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py b/kallithea/lib/dbmigrate/versions/002_version_1_1_0.py rename from rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py rename to kallithea/lib/dbmigrate/versions/002_version_1_1_0.py --- a/rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py +++ b/kallithea/lib/dbmigrate/versions/002_version_1_1_0.py @@ -5,10 +5,10 @@ from sqlalchemy import * from sqlalchemy.exc import DatabaseError from sqlalchemy.orm import relation, backref, class_mapper from sqlalchemy.orm.session import Session -from rhodecode.model.meta import Base +from kallithea.model.meta import Base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * log = logging.getLogger(__name__) @@ -68,13 +68,13 @@ def upgrade(migrate_engine): #========================================================================== # Add table `user_followings` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_1_0 import UserFollowing + from kallithea.lib.dbmigrate.schema.db_1_1_0 import UserFollowing UserFollowing().__table__.create() #========================================================================== # Add table `cache_invalidation` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_1_0 import CacheInvalidation + from kallithea.lib.dbmigrate.schema.db_1_1_0 import CacheInvalidation CacheInvalidation().__table__.create() return diff --git a/rhodecode/lib/dbmigrate/versions/003_version_1_2_0.py b/kallithea/lib/dbmigrate/versions/003_version_1_2_0.py rename from rhodecode/lib/dbmigrate/versions/003_version_1_2_0.py rename to kallithea/lib/dbmigrate/versions/003_version_1_2_0.py --- a/rhodecode/lib/dbmigrate/versions/003_version_1_2_0.py +++ b/kallithea/lib/dbmigrate/versions/003_version_1_2_0.py @@ -6,10 +6,10 @@ from sqlalchemy.exc import DatabaseError from sqlalchemy.orm import relation, backref, class_mapper from sqlalchemy.orm.session import Session -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base +from kallithea.model.meta import Base log = logging.getLogger(__name__) @@ -22,43 +22,43 @@ def upgrade(migrate_engine): #========================================================================== # Add table `groups`` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_2_0 import Group as Group + from kallithea.lib.dbmigrate.schema.db_1_2_0 import Group as Group Group().__table__.create() #========================================================================== # Add table `group_to_perm` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserRepoGroupToPerm + from kallithea.lib.dbmigrate.schema.db_1_2_0 import UserRepoGroupToPerm UserRepoGroupToPerm().__table__.create() #========================================================================== # Add table `users_groups` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroup + from kallithea.lib.dbmigrate.schema.db_1_2_0 import UserGroup UserGroup().__table__.create() #========================================================================== # Add table `users_groups_members` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroupMember + from kallithea.lib.dbmigrate.schema.db_1_2_0 import UserGroupMember UserGroupMember().__table__.create() #========================================================================== # Add table `users_group_repo_to_perm` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroupRepoToPerm + from kallithea.lib.dbmigrate.schema.db_1_2_0 import UserGroupRepoToPerm UserGroupRepoToPerm().__table__.create() #========================================================================== # Add table `users_group_to_perm` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroupToPerm + from kallithea.lib.dbmigrate.schema.db_1_2_0 import UserGroupToPerm UserGroupToPerm().__table__.create() #========================================================================== # Upgrade of `users` table #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_2_0 import User + from kallithea.lib.dbmigrate.schema.db_1_2_0 import User #add column ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) @@ -74,7 +74,7 @@ def upgrade(migrate_engine): #========================================================================== # Upgrade of `repositories` table #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_2_0 import Repository + from kallithea.lib.dbmigrate.schema.db_1_2_0 import Repository #ADD clone_uri column# @@ -103,7 +103,7 @@ def upgrade(migrate_engine): # Upgrade of `user_followings` table #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserFollowing + from kallithea.lib.dbmigrate.schema.db_1_2_0 import UserFollowing follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, diff --git a/rhodecode/lib/dbmigrate/versions/004_version_1_3_0.py b/kallithea/lib/dbmigrate/versions/004_version_1_3_0.py rename from rhodecode/lib/dbmigrate/versions/004_version_1_3_0.py rename to kallithea/lib/dbmigrate/versions/004_version_1_3_0.py --- a/rhodecode/lib/dbmigrate/versions/004_version_1_3_0.py +++ b/kallithea/lib/dbmigrate/versions/004_version_1_3_0.py @@ -6,10 +6,10 @@ from sqlalchemy.exc import DatabaseError from sqlalchemy.orm import relation, backref, class_mapper from sqlalchemy.orm.session import Session -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base +from kallithea.model.meta import Base log = logging.getLogger(__name__) @@ -21,31 +21,31 @@ def upgrade(migrate_engine): #========================================================================== # Add table `users_group_repo_group_to_perm` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserGroupRepoGroupToPerm + from kallithea.lib.dbmigrate.schema.db_1_3_0 import UserGroupRepoGroupToPerm UserGroupRepoGroupToPerm().__table__.create() #========================================================================== # Add table `changeset_comments` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import ChangesetComment + from kallithea.lib.dbmigrate.schema.db_1_3_0 import ChangesetComment ChangesetComment().__table__.create() #========================================================================== # Add table `notifications` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import Notification + from kallithea.lib.dbmigrate.schema.db_1_3_0 import Notification Notification().__table__.create() #========================================================================== # Add table `user_to_notification` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserNotification + from kallithea.lib.dbmigrate.schema.db_1_3_0 import UserNotification UserNotification().__table__.create() #========================================================================== # Add unique to table `users_group_to_perm` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserGroupToPerm + from kallithea.lib.dbmigrate.schema.db_1_3_0 import UserGroupToPerm tbl = UserGroupToPerm().__table__ cons = UniqueConstraint('users_group_id', 'permission_id', table=tbl) cons.create() @@ -53,7 +53,7 @@ def upgrade(migrate_engine): #========================================================================== # Fix unique constrain on table `user_logs` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserLog + from kallithea.lib.dbmigrate.schema.db_1_3_0 import UserLog tbl = UserLog().__table__ col = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) diff --git a/rhodecode/lib/dbmigrate/versions/005_version_1_3_0.py b/kallithea/lib/dbmigrate/versions/005_version_1_3_0.py rename from rhodecode/lib/dbmigrate/versions/005_version_1_3_0.py rename to kallithea/lib/dbmigrate/versions/005_version_1_3_0.py --- a/rhodecode/lib/dbmigrate/versions/005_version_1_3_0.py +++ b/kallithea/lib/dbmigrate/versions/005_version_1_3_0.py @@ -6,10 +6,10 @@ from sqlalchemy.exc import DatabaseError from sqlalchemy.orm import relation, backref, class_mapper from sqlalchemy.orm.session import Session -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base +from kallithea.model.meta import Base log = logging.getLogger(__name__) @@ -22,7 +22,7 @@ def upgrade(migrate_engine): #========================================================================== # Change unique constraints of table `repo_to_perm` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserRepoToPerm + from kallithea.lib.dbmigrate.schema.db_1_3_0 import UserRepoToPerm tbl = UserRepoToPerm().__table__ new_cons = UniqueConstraint('user_id', 'repository_id', 'permission_id', table=tbl) new_cons.create() @@ -47,7 +47,7 @@ def upgrade(migrate_engine): #========================================================================== # fix uniques of table `user_repo_group_to_perm` #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserRepoGroupToPerm + from kallithea.lib.dbmigrate.schema.db_1_3_0 import UserRepoGroupToPerm tbl = UserRepoGroupToPerm().__table__ new_cons = UniqueConstraint('group_id', 'permission_id', 'user_id', table=tbl) new_cons.create() diff --git a/rhodecode/lib/dbmigrate/versions/006_version_1_4_0.py b/kallithea/lib/dbmigrate/versions/006_version_1_4_0.py rename from rhodecode/lib/dbmigrate/versions/006_version_1_4_0.py rename to kallithea/lib/dbmigrate/versions/006_version_1_4_0.py --- a/rhodecode/lib/dbmigrate/versions/006_version_1_4_0.py +++ b/kallithea/lib/dbmigrate/versions/006_version_1_4_0.py @@ -7,12 +7,12 @@ from sqlalchemy.orm import relation, bac from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base -from rhodecode.model import meta -from rhodecode.lib.dbmigrate.versions import _reset_base +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base log = logging.getLogger(__name__) @@ -26,27 +26,27 @@ def upgrade(migrate_engine): #========================================================================== # USEREMAILMAP #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_4_0 import UserEmailMap + from kallithea.lib.dbmigrate.schema.db_1_4_0 import UserEmailMap tbl = UserEmailMap.__table__ tbl.create() #========================================================================== # PULL REQUEST #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_4_0 import PullRequest + from kallithea.lib.dbmigrate.schema.db_1_4_0 import PullRequest tbl = PullRequest.__table__ tbl.create() #========================================================================== # PULL REQUEST REVIEWERS #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_4_0 import PullRequestReviewers + from kallithea.lib.dbmigrate.schema.db_1_4_0 import PullRequestReviewers tbl = PullRequestReviewers.__table__ tbl.create() #========================================================================== # CHANGESET STATUS #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_4_0 import ChangesetStatus + from kallithea.lib.dbmigrate.schema.db_1_4_0 import ChangesetStatus tbl = ChangesetStatus.__table__ tbl.create() @@ -55,7 +55,7 @@ def upgrade(migrate_engine): #========================================================================== # USERS TABLE #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import User + from kallithea.lib.dbmigrate.schema.db_1_3_0 import User tbl = User.__table__ # change column name -> firstname @@ -74,7 +74,7 @@ def upgrade(migrate_engine): #========================================================================== # USERS GROUP TABLE #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserGroup + from kallithea.lib.dbmigrate.schema.db_1_3_0 import UserGroup tbl = UserGroup.__table__ # add inherit_default_permission column gr_inherit_default_permissions = Column( @@ -87,7 +87,7 @@ def upgrade(migrate_engine): #========================================================================== # REPOSITORIES #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import Repository + from kallithea.lib.dbmigrate.schema.db_1_3_0 import Repository tbl = Repository.__table__ # add enable locking column @@ -110,7 +110,7 @@ def upgrade(migrate_engine): #========================================================================== # GROUPS #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import RepoGroup + from kallithea.lib.dbmigrate.schema.db_1_3_0 import RepoGroup tbl = RepoGroup.__table__ # add enable locking column @@ -122,7 +122,7 @@ def upgrade(migrate_engine): #========================================================================== # CACHE INVALIDATION #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import CacheInvalidation + from kallithea.lib.dbmigrate.schema.db_1_3_0 import CacheInvalidation tbl = CacheInvalidation.__table__ # add INDEX for cache keys @@ -132,7 +132,7 @@ def upgrade(migrate_engine): #========================================================================== # NOTIFICATION #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import Notification + from kallithea.lib.dbmigrate.schema.db_1_3_0 import Notification tbl = Notification.__table__ # add index for notification type @@ -142,7 +142,7 @@ def upgrade(migrate_engine): #========================================================================== # CHANGESET_COMMENTS #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_3_0 import ChangesetComment + from kallithea.lib.dbmigrate.schema.db_1_3_0 import ChangesetComment tbl = ChangesetComment.__table__ col = ChangesetComment.__table__.columns.revision diff --git a/rhodecode/lib/dbmigrate/versions/007_version_1_4_0.py b/kallithea/lib/dbmigrate/versions/007_version_1_4_0.py rename from rhodecode/lib/dbmigrate/versions/007_version_1_4_0.py rename to kallithea/lib/dbmigrate/versions/007_version_1_4_0.py --- a/rhodecode/lib/dbmigrate/versions/007_version_1_4_0.py +++ b/kallithea/lib/dbmigrate/versions/007_version_1_4_0.py @@ -7,11 +7,11 @@ from sqlalchemy.orm import relation, bac from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base -from rhodecode.model import meta +from kallithea.model.meta import Base +from kallithea.model import meta log = logging.getLogger(__name__) @@ -25,7 +25,7 @@ def upgrade(migrate_engine): #========================================================================== # CHANGESET_COMMENTS #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_4_0 import ChangesetComment + from kallithea.lib.dbmigrate.schema.db_1_4_0 import ChangesetComment tbl_name = ChangesetComment.__tablename__ tbl = Table(tbl_name, MetaData(bind=migrate_engine), autoload=True, @@ -38,7 +38,7 @@ def upgrade(migrate_engine): #========================================================================== # REPOSITORY #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_4_0 import Repository + from kallithea.lib.dbmigrate.schema.db_1_4_0 import Repository tbl = Repository.__table__ updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None) diff --git a/rhodecode/lib/dbmigrate/versions/008_version_1_5_0.py b/kallithea/lib/dbmigrate/versions/008_version_1_5_0.py rename from rhodecode/lib/dbmigrate/versions/008_version_1_5_0.py rename to kallithea/lib/dbmigrate/versions/008_version_1_5_0.py --- a/rhodecode/lib/dbmigrate/versions/008_version_1_5_0.py +++ b/kallithea/lib/dbmigrate/versions/008_version_1_5_0.py @@ -7,12 +7,12 @@ from sqlalchemy.orm import relation, bac from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base -from rhodecode.model import meta -from rhodecode.lib.dbmigrate.versions import _reset_base +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base log = logging.getLogger(__name__) @@ -22,23 +22,24 @@ def upgrade(migrate_engine): Upgrade operations go here. Don't create your own engine; bind migrate_engine to your metadata """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_1_5_0 #========================================================================== # USER LOGS #========================================================================== - _reset_base(migrate_engine) - from rhodecode.lib.dbmigrate.schema.db_1_5_0 import UserLog - tbl = UserLog.__table__ + + tbl = db_1_5_0.UserLog.__table__ username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) # create username column username.create(table=tbl) - _Session = Session() + _Session = meta.Session() ## after adding that column fix all usernames - users_log = _Session.query(UserLog)\ - .options(joinedload(UserLog.user))\ - .options(joinedload(UserLog.repository)).all() + users_log = _Session.query(db_1_5_0.UserLog)\ + .options(joinedload(db_1_5_0.UserLog.user))\ + .options(joinedload(db_1_5_0.UserLog.repository)).all() for entry in users_log: entry.username = entry.user.username @@ -46,8 +47,7 @@ def upgrade(migrate_engine): _Session.commit() #alter username to not null - from rhodecode.lib.dbmigrate.schema.db_1_5_0 import UserLog - tbl_name = UserLog.__tablename__ + tbl_name = db_1_5_0.UserLog.__tablename__ tbl = Table(tbl_name, MetaData(bind=migrate_engine), autoload=True, autoload_with=migrate_engine) @@ -56,7 +56,73 @@ def upgrade(migrate_engine): # remove nullability from revision field col.alter(nullable=False) + # issue fixups + fixups(db_1_5_0, meta.Session) + def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine + + +def fixups(models, _SESSION): + # ** create default permissions ** # + #===================================== + for p in models.Permission.PERMS: + if not models.Permission.get_by_key(p[0]): + new_perm = models.Permission() + new_perm.permission_name = p[0] + new_perm.permission_longname = p[0] #translation err with p[1] + print 'Creating new permission %s' % p[0] + _SESSION().add(new_perm) + + _SESSION().commit() + + # ** populate default permissions ** # + #===================================== + + user = models.User.query().filter(models.User.username == 'default').scalar() + + def _make_perm(perm): + new_perm = models.UserToPerm() + new_perm.user = user + new_perm.permission = models.Permission.get_by_key(perm) + return new_perm + + def _get_group(perm_name): + return '.'.join(perm_name.split('.')[:1]) + + perms = models.UserToPerm.query().filter(models.UserToPerm.user == user).all() + defined_perms_groups = map(_get_group, + (x.permission.permission_name for x in perms)) + log.debug('GOT ALREADY DEFINED:%s' % perms) + DEFAULT_PERMS = models.Permission.DEFAULT_USER_PERMISSIONS + + # for every default permission that needs to be created, we check if + # it's group is already defined, if it's not we create default perm + for perm_name in DEFAULT_PERMS: + gr = _get_group(perm_name) + if gr not in defined_perms_groups: + log.debug('GR:%s not found, creating permission %s' + % (gr, perm_name)) + new_perm = _make_perm(perm_name) + _SESSION().add(new_perm) + _SESSION().commit() + + # ** create default options ** # + #=============================== + skip_existing = True + for k, v in [ + ('default_repo_enable_locking', False), + ('default_repo_enable_downloads', False), + ('default_repo_enable_statistics', False), + ('default_repo_private', False), + ('default_repo_type', 'hg')]: + + if skip_existing and models.Setting.get_by_name(k) is not None: + log.debug('Skipping option %s' % k) + continue + setting = models.Setting(k, v) + _SESSION().add(setting) + + _SESSION().commit() diff --git a/rhodecode/lib/dbmigrate/versions/009_version_1_5_1.py b/kallithea/lib/dbmigrate/versions/009_version_1_5_1.py rename from rhodecode/lib/dbmigrate/versions/009_version_1_5_1.py rename to kallithea/lib/dbmigrate/versions/009_version_1_5_1.py --- a/rhodecode/lib/dbmigrate/versions/009_version_1_5_1.py +++ b/kallithea/lib/dbmigrate/versions/009_version_1_5_1.py @@ -7,11 +7,11 @@ from sqlalchemy.orm import relation, bac from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base -from rhodecode.model import meta +from kallithea.model.meta import Base +from kallithea.model import meta log = logging.getLogger(__name__) diff --git a/rhodecode/lib/dbmigrate/versions/010_version_1_5_2.py b/kallithea/lib/dbmigrate/versions/010_version_1_5_2.py rename from rhodecode/lib/dbmigrate/versions/010_version_1_5_2.py rename to kallithea/lib/dbmigrate/versions/010_version_1_5_2.py --- a/rhodecode/lib/dbmigrate/versions/010_version_1_5_2.py +++ b/kallithea/lib/dbmigrate/versions/010_version_1_5_2.py @@ -7,12 +7,12 @@ from sqlalchemy.orm import relation, bac from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base -from rhodecode.model import meta -from rhodecode.lib.dbmigrate.versions import _reset_base +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify log = logging.getLogger(__name__) @@ -23,28 +23,34 @@ def upgrade(migrate_engine): Don't create your own engine; bind migrate_engine to your metadata """ _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_1_5_2 #========================================================================== # USER LOGS #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_5_2 import UserIpMap - tbl = UserIpMap.__table__ + tbl = db_1_5_2.UserIpMap.__table__ tbl.create() #========================================================================== # REPOSITORIES #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_5_2 import Repository - tbl = Repository.__table__ + tbl = db_1_5_2.Repository.__table__ changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) # create username column changeset_cache.create(table=tbl) - #fix cache data - repositories = Repository.getAll() - for entry in repositories: - entry.update_changeset_cache() + # issue fixups + fixups(db_1_5_2, meta.Session) def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Upgrading repositories Caches') + repositories = models.Repository.getAll() + for repo in repositories: + print repo + repo.update_changeset_cache() + _SESSION().commit() diff --git a/rhodecode/lib/dbmigrate/versions/011_version_1_6_0.py b/kallithea/lib/dbmigrate/versions/011_version_1_6_0.py rename from rhodecode/lib/dbmigrate/versions/011_version_1_6_0.py rename to kallithea/lib/dbmigrate/versions/011_version_1_6_0.py --- a/rhodecode/lib/dbmigrate/versions/011_version_1_6_0.py +++ b/kallithea/lib/dbmigrate/versions/011_version_1_6_0.py @@ -7,12 +7,12 @@ from sqlalchemy.orm import relation, bac from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base -from rhodecode.model import meta -from rhodecode.lib.dbmigrate.versions import _reset_base +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify log = logging.getLogger(__name__) @@ -23,14 +23,27 @@ def upgrade(migrate_engine): Don't create your own engine; bind migrate_engine to your metadata """ _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_1_6_0 + #========================================================================== # USER LOGS #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_6_0 import RepositoryField - tbl = RepositoryField.__table__ + tbl = db_1_6_0.RepositoryField.__table__ tbl.create() + # issue fixups + fixups(db_1_6_0, meta.Session) + def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Upgrading repositories Caches') + repositories = models.Repository.getAll() + for repo in repositories: + print repo + repo.update_changeset_cache() + _SESSION().commit() diff --git a/rhodecode/lib/dbmigrate/versions/012_version_1_7_0.py b/kallithea/lib/dbmigrate/versions/012_version_1_7_0.py rename from rhodecode/lib/dbmigrate/versions/012_version_1_7_0.py rename to kallithea/lib/dbmigrate/versions/012_version_1_7_0.py --- a/rhodecode/lib/dbmigrate/versions/012_version_1_7_0.py +++ b/kallithea/lib/dbmigrate/versions/012_version_1_7_0.py @@ -7,12 +7,12 @@ from sqlalchemy.orm import relation, bac from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base -from rhodecode.model import meta -from rhodecode.lib.dbmigrate.versions import _reset_base +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base log = logging.getLogger(__name__) @@ -23,46 +23,128 @@ def upgrade(migrate_engine): Don't create your own engine; bind migrate_engine to your metadata """ _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_1_7_0 #========================================================================== # UserUserGroupToPerm #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_7_0 import UserUserGroupToPerm - tbl = UserUserGroupToPerm.__table__ + tbl = db_1_7_0.UserUserGroupToPerm.__table__ tbl.create() #========================================================================== # UserGroupUserGroupToPerm #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_7_0 import UserGroupUserGroupToPerm - tbl = UserGroupUserGroupToPerm.__table__ + tbl = db_1_7_0.UserGroupUserGroupToPerm.__table__ tbl.create() #========================================================================== # Gist #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_7_0 import Gist - tbl = Gist.__table__ + tbl = db_1_7_0.Gist.__table__ tbl.create() #========================================================================== # UserGroup #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_7_0 import UserGroup - tbl = UserGroup.__table__ - user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=False, default=None) + tbl = db_1_7_0.UserGroup.__table__ + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), + nullable=True, unique=False, default=None) # create username column user_id.create(table=tbl) #========================================================================== # RepoGroup #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_7_0 import RepoGroup - tbl = RepoGroup.__table__ - user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=False, default=None) + tbl = db_1_7_0.RepoGroup.__table__ + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), + nullable=True, unique=False, default=None) # create username column user_id.create(table=tbl) + # issue fixups + fixups(db_1_7_0, meta.Session) + + def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine + + +def fixups(models, _SESSION): + # ** create default permissions ** # + #===================================== + for p in models.Permission.PERMS: + if not models.Permission.get_by_key(p[0]): + new_perm = models.Permission() + new_perm.permission_name = p[0] + new_perm.permission_longname = p[0] #translation err with p[1] + _SESSION().add(new_perm) + + _SESSION().commit() + + # ** populate default permissions ** # + #===================================== + + user = models.User.query().filter(models.User.username == 'default').scalar() + + def _make_perm(perm): + new_perm = models.UserToPerm() + new_perm.user = user + new_perm.permission = models.Permission.get_by_key(perm) + return new_perm + + def _get_group(perm_name): + return '.'.join(perm_name.split('.')[:1]) + + perms = models.UserToPerm.query().filter(models.UserToPerm.user == user).all() + defined_perms_groups = map(_get_group, + (x.permission.permission_name for x in perms)) + log.debug('GOT ALREADY DEFINED:%s' % perms) + DEFAULT_PERMS = models.Permission.DEFAULT_USER_PERMISSIONS + + # for every default permission that needs to be created, we check if + # it's group is already defined, if it's not we create default perm + for perm_name in DEFAULT_PERMS: + gr = _get_group(perm_name) + if gr not in defined_perms_groups: + log.debug('GR:%s not found, creating permission %s' + % (gr, perm_name)) + new_perm = _make_perm(perm_name) + _SESSION().add(new_perm) + _SESSION().commit() + + #fix all usergroups + + def _create_default_perms(user_group): + # create default permission + default_perm = 'usergroup.read' + def_user = models.User.get_default_user() + for p in def_user.user_perms: + if p.permission.permission_name.startswith('usergroup.'): + default_perm = p.permission.permission_name + break + + user_group_to_perm = models.UserUserGroupToPerm() + user_group_to_perm.permission = models.Permission.get_by_key(default_perm) + + user_group_to_perm.user_group = user_group + user_group_to_perm.user_id = def_user.user_id + return user_group_to_perm + + for ug in models.UserGroup.get_all(): + perm_obj = _create_default_perms(ug) + _SESSION().add(perm_obj) + _SESSION().commit() + + adm = models.User.get_first_admin() + # fix owners of UserGroup + for ug in _SESSION().query(models.UserGroup).all(): + ug.user_id = adm.user_id + _SESSION().add(ug) + _SESSION().commit() + + # fix owners of RepoGroup + for ug in _SESSION().query(models.RepoGroup).all(): + ug.user_id = adm.user_id + _SESSION().add(ug) + _SESSION().commit() diff --git a/rhodecode/lib/dbmigrate/versions/013_version_1_7_0.py b/kallithea/lib/dbmigrate/versions/013_version_1_7_0.py rename from rhodecode/lib/dbmigrate/versions/013_version_1_7_0.py rename to kallithea/lib/dbmigrate/versions/013_version_1_7_0.py --- a/rhodecode/lib/dbmigrate/versions/013_version_1_7_0.py +++ b/kallithea/lib/dbmigrate/versions/013_version_1_7_0.py @@ -7,12 +7,12 @@ from sqlalchemy.orm import relation, bac from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base -from rhodecode.model import meta -from rhodecode.lib.dbmigrate.versions import _reset_base +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base log = logging.getLogger(__name__) @@ -28,7 +28,7 @@ def upgrade(migrate_engine): #========================================================================== # UserGroup #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_7_0 import UserGroup + from kallithea.lib.dbmigrate.schema.db_1_7_0 import UserGroup tbl = UserGroup.__table__ user_id = tbl.columns.user_id user_id.alter(nullable=False) @@ -36,7 +36,7 @@ def upgrade(migrate_engine): #========================================================================== # RepoGroup #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_7_0 import RepoGroup + from kallithea.lib.dbmigrate.schema.db_1_7_0 import RepoGroup tbl = RepoGroup.__table__ user_id = tbl.columns.user_id user_id.alter(nullable=False) diff --git a/rhodecode/lib/dbmigrate/versions/014_version_1_7_1.py b/kallithea/lib/dbmigrate/versions/014_version_1_7_1.py rename from rhodecode/lib/dbmigrate/versions/014_version_1_7_1.py rename to kallithea/lib/dbmigrate/versions/014_version_1_7_1.py --- a/rhodecode/lib/dbmigrate/versions/014_version_1_7_1.py +++ b/kallithea/lib/dbmigrate/versions/014_version_1_7_1.py @@ -7,12 +7,12 @@ from sqlalchemy.orm import relation, bac from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * -from rhodecode.model.meta import Base -from rhodecode.model import meta -from rhodecode.lib.dbmigrate.versions import _reset_base +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base log = logging.getLogger(__name__) @@ -23,16 +23,28 @@ def upgrade(migrate_engine): Don't create your own engine; bind migrate_engine to your metadata """ _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_1_7_0 #========================================================================== # Gist #========================================================================== - from rhodecode.lib.dbmigrate.schema.db_1_7_0 import Gist - tbl = Gist.__table__ + tbl = db_1_7_0.Gist.__table__ user_id = tbl.columns.gist_expires user_id.alter(type=Float(53)) + # issue fixups + fixups(db_1_7_0, meta.Session) + def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine + + +def fixups(models, _SESSION): + # fix nullable columns on last_update + for r in models.Repository().get_all(): + if r.updated_on is None: + r.updated_on = datetime.datetime.fromtimestamp(0) + _SESSION().add(r) + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/015_version_1_8_0.py b/kallithea/lib/dbmigrate/versions/015_version_1_8_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/015_version_1_8_0.py @@ -0,0 +1,82 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_1_8_0 + tbl = db_1_8_0.Setting.__table__ + app_settings_type = Column("app_settings_type", + String(255, convert_unicode=False, assert_unicode=None), + nullable=True, unique=None, default=None) + app_settings_type.create(table=tbl) + + # issue fixups + fixups(db_1_8_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Fixing default options now...') + + settings = [ + #general + ('realm', '', 'unicode'), + ('title', '', 'unicode'), + ('ga_code', '', 'unicode'), + ('show_public_icon', False, 'bool'), + ('show_private_icon', True, 'bool'), + ('stylify_metatags', True, 'bool'), + + # defaults + ('default_repo_enable_locking', False, 'bool'), + ('default_repo_enable_downloads', False, 'bool'), + ('default_repo_enable_statistics', False, 'bool'), + ('default_repo_private', False, 'bool'), + ('default_repo_type', 'hg', 'unicode'), + + #other + ('dashboard_items', 100, 'int'), + ('show_version', True, 'bool') + ] + + for name, default, type_ in settings: + setting = models.Setting.get_by_name(name) + if not setting: + # if we don't have this option create it + setting = models.Setting(name, default, type_) + + # fix certain key to new defaults + if name in ['title', 'show_public_icon']: + # change title if it's only the default + if name == 'title' and setting.app_settings_value == 'Kallithea': + setting.app_settings_value = default + else: + setting.app_settings_value = default + + setting._app_settings_type = type_ + _SESSION().add(setting) + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/016_version_2_0_0.py b/kallithea/lib/dbmigrate/versions/016_version_2_0_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/016_version_2_0_0.py @@ -0,0 +1,70 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea import EXTERN_TYPE_INTERNAL +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_0_0 + tbl = db_2_0_0.User.__table__ + + extern_type = Column("extern_type", + String(255, convert_unicode=False, assert_unicode=None), + nullable=True, unique=None, default=None) + extern_type.create(table=tbl) + + extern_name = Column("extern_name", String(255, convert_unicode=False, assert_unicode=None), + nullable=True, unique=None, default=None) + extern_name.create(table=tbl) + + created_on = Column('created_on', DateTime(timezone=False), + nullable=True, default=datetime.datetime.now) + created_on.create(table=tbl) + + # issue fixups + fixups(db_2_0_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Fixing default created on') + + for usr in models.User.get_all(): + usr.created_on = datetime.datetime.now() + _SESSION().add(usr) + _SESSION().commit() + + notify('Migrating LDAP attribute to extern') + for usr in models.User.get_all(): + ldap_dn = usr.ldap_dn + if ldap_dn: + usr.extern_name = ldap_dn + usr.extern_type = 'ldap' + else: + usr.extern_name = EXTERN_TYPE_INTERNAL + usr.extern_type = EXTERN_TYPE_INTERNAL + _SESSION().add(usr) + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/017_version_2_0_0.py b/kallithea/lib/dbmigrate/versions/017_version_2_0_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/017_version_2_0_0.py @@ -0,0 +1,53 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_0_0 + tbl = db_2_0_0.UserGroup.__table__ + + user_group_description = Column("user_group_description", + String(10000, convert_unicode=False, + assert_unicode=None), nullable=True, + unique=None, default=None) + user_group_description.create(table=tbl) + + created_on = Column('created_on', DateTime(timezone=False), + nullable=True, default=datetime.datetime.now) + created_on.create(table=tbl) + + # issue fixups + fixups(db_2_0_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Fixing default created on') + + for gr in models.UserGroup.get_all(): + gr.created_on = datetime.datetime.now() + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/018_version_2_0_0.py b/kallithea/lib/dbmigrate/versions/018_version_2_0_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/018_version_2_0_0.py @@ -0,0 +1,78 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_0_0 + + # issue fixups + fixups(db_2_0_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Fixing default auth modules') + plugins = 'kallithea.lib.auth_modules.auth_internal' + opts = [] + ldap_enabled = str2bool(getattr( + models.Setting.get_by_name('ldap_active'), + 'app_settings_value', False)) + if ldap_enabled: + plugins += ',kallithea.lib.auth_modules.auth_ldap' + opts.append(('auth_ldap_enabled', 'True', 'bool')) + + opts.append(('auth_plugins', plugins, 'list'),) + opts.append(('auth_internal_enabled', 'True', 'bool')) + + for name, default, type_ in opts: + setting = models.Setting.get_by_name(name) + if not setting: + # if we don't have this option create it + setting = models.Setting(name, default, type_) + + _SESSION().add(setting) + _SESSION().commit() + + #copy over the LDAP settings + old_ldap = [('ldap_active', 'false', 'bool'), ('ldap_host', '', 'unicode'), + ('ldap_port', '389', 'int'), ('ldap_tls_kind', 'PLAIN', 'unicode'), + ('ldap_tls_reqcert', '', 'unicode'), ('ldap_dn_user', '', 'unicode'), + ('ldap_dn_pass', '', 'unicode'), ('ldap_base_dn', '', 'unicode'), + ('ldap_filter', '', 'unicode'), ('ldap_search_scope', '', 'unicode'), + ('ldap_attr_login', '', 'unicode'), ('ldap_attr_firstname', '', 'unicode'), + ('ldap_attr_lastname', '', 'unicode'), ('ldap_attr_email', '', 'unicode')] + for k, v, t in old_ldap: + old_setting = models.Setting.get_by_name(k) + name = 'auth_%s' % k + setting = models.Setting.get_by_name(name) + if not setting: + # if we don't have this option create it + setting = models.Setting(name, old_setting.app_settings_value, t) + + _SESSION().add(setting) + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/019_version_2_0_0.py b/kallithea/lib/dbmigrate/versions/019_version_2_0_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/019_version_2_0_0.py @@ -0,0 +1,42 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_0_0 + tbl = db_2_0_0.Setting.__table__ + settings_value = tbl.columns.app_settings_value + settings_value.alter(type=String(4096)) + + # issue fixups + fixups(db_2_0_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + return diff --git a/kallithea/lib/dbmigrate/versions/020_version_2_0_1.py b/kallithea/lib/dbmigrate/versions/020_version_2_0_1.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/020_version_2_0_1.py @@ -0,0 +1,46 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea import EXTERN_TYPE_INTERNAL +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_0_1 + + # issue fixups + fixups(db_2_0_1, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + #fix all empty extern type users to default 'internal' + for usr in models.User.query().all(): + if not usr.extern_name: + usr.extern_name = EXTERN_TYPE_INTERNAL + usr.extern_type = EXTERN_TYPE_INTERNAL + _SESSION().add(usr) + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/021_version_2_0_2.py b/kallithea/lib/dbmigrate/versions/021_version_2_0_2.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/021_version_2_0_2.py @@ -0,0 +1,76 @@ +import os +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_0_1 + tbl = db_2_0_1.RepoGroup.__table__ + + created_on = Column('created_on', DateTime(timezone=False), nullable=True, + default=datetime.datetime.now) + created_on.create(table=tbl) + + #fix null values on certain columns when upgrading from older releases + tbl = db_2_0_1.UserLog.__table__ + col = tbl.columns.user_id + col.alter(nullable=True) + + tbl = db_2_0_1.UserFollowing.__table__ + col = tbl.columns.follows_repository_id + col.alter(nullable=True) + + tbl = db_2_0_1.UserFollowing.__table__ + col = tbl.columns.follows_user_id + col.alter(nullable=True) + + # issue fixups + fixups(db_2_0_1, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Fixing default created on for repo groups') + + for gr in models.RepoGroup.get_all(): + gr.created_on = datetime.datetime.now() + _SESSION().add(gr) + _SESSION().commit() + + repo_store_path = models.Ui.get_repos_location() + _store = os.path.join(repo_store_path, '.cache', 'largefiles') + notify('Setting largefiles usercache') + print _store + + if not models.Ui.get_by_key('usercache'): + largefiles = models.Ui() + largefiles.ui_section = 'largefiles' + largefiles.ui_key = 'usercache' + largefiles.ui_value = _store + _SESSION().add(largefiles) + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/022_version_2_0_2.py b/kallithea/lib/dbmigrate/versions/022_version_2_0_2.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/022_version_2_0_2.py @@ -0,0 +1,70 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_0_2 + + # issue fixups + fixups(db_2_0_2, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('fixing new schema for landing_rev') + + for repo in models.Repository.get_all(): + print u'repo %s old landing rev is: %s' % (repo, repo.landing_rev) + _rev = repo.landing_rev[1] + _rev_type = 'rev' # default + + if _rev in ['default', 'master']: + _rev_type = 'branch' + elif _rev in ['tip']: + _rev_type = 'rev' + else: + try: + scm = repo.scm_instance + if scm: + known_branches = scm.branches.keys() + known_bookmarks = scm.bookmarks.keys() + if _rev in known_branches: + _rev_type = 'branch' + elif _rev in known_bookmarks: + _rev_type = 'book' + except Exception, e: + print e + print 'continue...' + #we don't want any error to break the process + pass + + _new_landing_rev = '%s:%s' % (_rev_type, _rev) + print u'setting to %s' % _new_landing_rev + repo.landing_rev = _new_landing_rev + _SESSION().add(repo) + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/023_version_2_1_0.py b/kallithea/lib/dbmigrate/versions/023_version_2_1_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/023_version_2_1_0.py @@ -0,0 +1,42 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_1_0 + + tbl = db_2_1_0.UserApiKeys.__table__ + tbl.create() + + # issue fixups + fixups(db_2_1_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + pass diff --git a/kallithea/lib/dbmigrate/versions/024_version_2_1_0.py b/kallithea/lib/dbmigrate/versions/024_version_2_1_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/024_version_2_1_0.py @@ -0,0 +1,67 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_1_0 + + # issue fixups + fixups(db_2_1_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + from pylons import config + from kallithea.lib.utils2 import str2bool + + notify('migrating options from .ini file') + use_gravatar = str2bool(config.get('use_gravatar')) + print('Setting gravatar use to: %s' % use_gravatar) + sett = models.Setting.create_or_update('use_gravatar', + use_gravatar, 'bool') + _SESSION().add(sett) + _SESSION.commit() + #set the new format of gravatar URL + gravatar_url = models.User.DEFAULT_GRAVATAR_URL + if config.get('alternative_gravatar_url'): + gravatar_url = config.get('alternative_gravatar_url') + + print('Setting gravatar url to:%s' % gravatar_url) + sett = models.Setting.create_or_update('gravatar_url', + gravatar_url, 'unicode') + _SESSION().add(sett) + _SESSION.commit() + + #now create new changed value of clone_url + clone_uri_tmpl = models.Repository.DEFAULT_CLONE_URI + print('settings new clone url template to %s' % clone_uri_tmpl) + + sett = models.Setting.create_or_update('clone_uri_tmpl', + clone_uri_tmpl, 'unicode') + _SESSION().add(sett) + _SESSION.commit() diff --git a/kallithea/lib/dbmigrate/versions/025_version_2_1_0.py b/kallithea/lib/dbmigrate/versions/025_version_2_1_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/025_version_2_1_0.py @@ -0,0 +1,43 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_1_0 + + # issue fixups + fixups(db_2_1_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Creating upgrade URL') + sett = models.Setting.create_or_update('update_url', + models.Setting.DEFAULT_UPDATE_URL, 'unicode') + _SESSION().add(sett) + _SESSION.commit() diff --git a/kallithea/lib/dbmigrate/versions/026_version_2_2_0.py b/kallithea/lib/dbmigrate/versions/026_version_2_2_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/026_version_2_2_0.py @@ -0,0 +1,44 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_2_0 + + tbl = db_2_2_0.User.__table__ + + user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data + user_data.create(table=tbl) + + # issue fixups + fixups(db_2_2_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + pass diff --git a/kallithea/lib/dbmigrate/versions/027_version_2_2_0.py b/kallithea/lib/dbmigrate/versions/027_version_2_2_0.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/027_version_2_2_0.py @@ -0,0 +1,59 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_2_0 + + # issue fixups + fixups(db_2_2_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + # ** create default permissions ** # + #===================================== + for p in models.Permission.PERMS: + if not models.Permission.get_by_key(p[0]): + new_perm = models.Permission() + new_perm.permission_name = p[0] + new_perm.permission_longname = p[0] #translation err with p[1] + print 'Creating new permission %s' % p[0] + _SESSION().add(new_perm) + + _SESSION().commit() + + # ** set default create_on_write to active + user = models.User.get_default_user() + _def = 'hg.create.write_on_repogroup.true' + new = models.UserToPerm() + new.user = user + new.permission = models.Permission.get_by_key(_def) + print 'Setting default to %s' % _def + _SESSION().add(new) + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/028_version_2_2_3.py b/kallithea/lib/dbmigrate/versions/028_version_2_2_3.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/028_version_2_2_3.py @@ -0,0 +1,44 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_2_0 + + tbl = db_2_2_0.UserGroup.__table__ + + user_data = Column("group_data", LargeBinary(), nullable=True) # JSON data + user_data.create(table=tbl) + + # issue fixups + fixups(db_2_2_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + pass diff --git a/kallithea/lib/dbmigrate/versions/029_version_2_2_3.py b/kallithea/lib/dbmigrate/versions/029_version_2_2_3.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/029_version_2_2_3.py @@ -0,0 +1,52 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_2_0 + + # issue fixups + fixups(db_2_2_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Adding grid items options now...') + + settings = [ + ('admin_grid_items', 25, 'int'), # old hardcoded value was 25 + ] + + for name, default, type_ in settings: + setting = models.Setting.get_by_name(name) + if not setting: + # if we don't have this option create it + setting = models.Setting(name, default, type_) + setting._app_settings_type = type_ + _SESSION().add(setting) + _SESSION().commit() diff --git a/kallithea/lib/dbmigrate/versions/030_version_2_2_3.py b/kallithea/lib/dbmigrate/versions/030_version_2_2_3.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/030_version_2_2_3.py @@ -0,0 +1,44 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_2_0 + + tbl = db_2_2_0.Repository.__table__ + + repo_state = Column("repo_state", String(255), nullable=True) + repo_state.create(table=tbl) + + # issue fixups + fixups(db_2_2_0, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + pass diff --git a/kallithea/lib/dbmigrate/versions/031_version_2_2_3.py b/kallithea/lib/dbmigrate/versions/031_version_2_2_3.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/dbmigrate/versions/031_version_2_2_3.py @@ -0,0 +1,45 @@ +import logging +import datetime + +from sqlalchemy import * +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import relation, backref, class_mapper, joinedload +from sqlalchemy.orm.session import Session +from sqlalchemy.ext.declarative import declarative_base + +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * +from kallithea.lib.utils2 import str2bool + +from kallithea.model.meta import Base +from kallithea.model import meta +from kallithea.lib.dbmigrate.versions import _reset_base, notify + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from kallithea.lib.dbmigrate.schema import db_2_2_3 + + # issue fixups + fixups(db_2_2_3, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + notify('Creating repository states') + for repo in models.Repository.get_all(): + _state = models.Repository.STATE_CREATED + print 'setting repo %s state to "%s"' % (repo, _state) + repo.repo_state = _state + _SESSION().add(repo) + _SESSION().commit() diff --git a/rhodecode/lib/dbmigrate/versions/__init__.py b/kallithea/lib/dbmigrate/versions/__init__.py rename from rhodecode/lib/dbmigrate/versions/__init__.py rename to kallithea/lib/dbmigrate/versions/__init__.py --- a/rhodecode/lib/dbmigrate/versions/__init__.py +++ b/kallithea/lib/dbmigrate/versions/__init__.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.dbmigrate.versions.__init__ - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Package containing new versions of database models - - :created_on: Dec 11, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,17 +11,40 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.dbmigrate.versions.__init__ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Package containing new versions of database models + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Dec 11, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from sqlalchemy import * from sqlalchemy.exc import DatabaseError from sqlalchemy.orm import relation, backref, class_mapper, joinedload -from sqlalchemy.orm.session import Session from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import scoped_session, sessionmaker +from kallithea.lib.dbmigrate.migrate import * +from kallithea.lib.dbmigrate.migrate.changeset import * + +from kallithea.model import meta + -from rhodecode.lib.dbmigrate.migrate import * -from rhodecode.lib.dbmigrate.migrate.changeset import * - -from rhodecode.model.meta import Base -from rhodecode.model import meta +def notify(msg, caps=True): + """ + Notification for migrations messages + """ + ml = len(msg) + (4 * 2) + formatted_msg = ('\n%s\n*** %s ***\n%s' % ('*' * ml, msg, '*' * ml)) + if caps: + formatted_msg = formatted_msg.upper() + print(formatted_msg) def _reset_base(migrate_engine): @@ -41,4 +53,10 @@ def _reset_base(migrate_engine): Base.metadata.clear() Base.metadata = MetaData() Base.metadata.bind = migrate_engine + + # new session and base + #meta.Session = scoped_session(sessionmaker(expire_on_commit=True,)) + #meta.Session.configure(bind=migrate_engine) meta.Base = Base + + notify('SQLA BASE RESET !') diff --git a/rhodecode/lib/diffs.py b/kallithea/lib/diffs.py rename from rhodecode/lib/diffs.py rename to kallithea/lib/diffs.py --- a/rhodecode/lib/diffs.py +++ b/kallithea/lib/diffs.py @@ -1,17 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.diffs - ~~~~~~~~~~~~~~~~~~~ - - Set of diffing helpers, previously part of vcs - - - :created_on: Dec 4, 2011 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :original copyright: 2007-2008 by Armin Ronacher - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -24,7 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.diffs +~~~~~~~~~~~~~~~~~~~ +Set of diffing helpers, previously part of vcs + + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Dec 4, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import re import difflib import logging @@ -33,11 +33,11 @@ from itertools import tee, imap from pylons.i18n.translation import _ -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.nodes import FileNode, SubModuleNode -from rhodecode.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.helpers import escape -from rhodecode.lib.utils2 import safe_unicode, safe_str +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.nodes import FileNode, SubModuleNode +from kallithea.lib.vcs.backends.base import EmptyChangeset +from kallithea.lib.helpers import escape +from kallithea.lib.utils2 import safe_unicode, safe_str log = logging.getLogger(__name__) @@ -438,7 +438,9 @@ class DiffProcessor(object): chunks = [] if op == 'D' and chunks: - chunks = [] + # if not full diff mode show deleted file contents + if self.diff_limit is not None: + chunks = [] chunks.insert(0, [{ 'old_lineno': '', diff --git a/rhodecode/lib/exceptions.py b/kallithea/lib/exceptions.py rename from rhodecode/lib/exceptions.py rename to kallithea/lib/exceptions.py --- a/rhodecode/lib/exceptions.py +++ b/kallithea/lib/exceptions.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.exceptions - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Set of custom exceptions used in RhodeCode - - :created_on: Nov 17, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.exceptions +~~~~~~~~~~~~~~~~~~~~~~~~ + +Set of custom exceptions used in Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Nov 17, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" from webob.exc import HTTPClientError @@ -72,15 +74,15 @@ class NonRelativePathError(Exception): class HTTPLockedRC(HTTPClientError): """ - Special Exception For locked Repos in RhodeCode, the return code can + Special Exception For locked Repos in Kallithea, the return code can be overwritten by _code keyword argument passed into constructors """ code = 423 title = explanation = 'Repository Locked' def __init__(self, reponame, username, *args, **kwargs): - from rhodecode import CONFIG - from rhodecode.lib.utils2 import safe_int + from kallithea import CONFIG + from kallithea.lib.utils2 import safe_int _code = CONFIG.get('lock_ret_code') self.code = safe_int(_code, self.code) self.title = self.explanation = ('Repository `%s` locked by ' diff --git a/rhodecode/lib/ext_json.py b/kallithea/lib/ext_json.py rename from rhodecode/lib/ext_json.py rename to kallithea/lib/ext_json.py diff --git a/rhodecode/lib/graphmod.py b/kallithea/lib/graphmod.py rename from rhodecode/lib/graphmod.py rename to kallithea/lib/graphmod.py --- a/rhodecode/lib/graphmod.py +++ b/kallithea/lib/graphmod.py @@ -1,3 +1,16 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . """ Modified mercurial DAG graph functions that re-uses VCS structure @@ -36,7 +49,7 @@ def _dagwalker(repo, revs, alias): repo = repo elif alias == 'git': def cl(rev): - return [x.revision for x in repo[rev].parents()] + return [x.revision for x in repo[rev].parents] repo = repo lowestrev = min(revs) diff --git a/rhodecode/lib/helpers.py b/kallithea/lib/helpers.py rename from rhodecode/lib/helpers.py rename to kallithea/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/kallithea/lib/helpers.py @@ -1,4 +1,18 @@ -"""Helper functions +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +Helper functions Consists of functions to typically be used within templates, but also available to Controllers. This module is available to both as 'h'. @@ -40,17 +54,17 @@ from webhelpers.paginate import Page as from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \ convert_boolean_attrs, NotGiven, _make_safe_id_component -from rhodecode.lib.annotate import annotate_highlight -from rhodecode.lib.utils import repo_name_slug, get_custom_lexer -from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \ +from kallithea.lib.annotate import annotate_highlight +from kallithea.lib.utils import repo_name_slug, get_custom_lexer +from kallithea.lib.utils2 import str2bool, safe_unicode, safe_str, \ get_changeset_safe, datetime_to_time, time_to_datetime, AttributeDict,\ safe_int -from rhodecode.lib.markup_renderer import MarkupRenderer -from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError -from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyChangeset -from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT -from rhodecode.model.changeset_status import ChangesetStatusModel -from rhodecode.model.db import URL_SEP, Permission +from kallithea.lib.markup_renderer import MarkupRenderer +from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError +from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset +from kallithea.config.conf import DATE_FORMAT, DATETIME_FORMAT +from kallithea.model.changeset_status import ChangesetStatusModel +from kallithea.model.db import URL_SEP, Permission log = logging.getLogger(__name__) @@ -351,7 +365,7 @@ def pygmentize_annotation(repo_name, fil def is_following_repo(repo_name, user_id): - from rhodecode.model.scm import ScmModel + from kallithea.model.scm import ScmModel return ScmModel().is_following_repo(repo_name, user_id) class _Message(object): @@ -365,8 +379,8 @@ class _Message(object): """ def __init__(self, category, message): - self.category=category - self.message=message + self.category = category + self.message = message def __str__(self): return self.message @@ -393,9 +407,9 @@ flash = Flash() #============================================================================== # SCM FILTERS available via h. #============================================================================== -from rhodecode.lib.vcs.utils import author_name, author_email -from rhodecode.lib.utils2 import credentials_filter, age as _age -from rhodecode.model.db import User, ChangesetStatus +from kallithea.lib.vcs.utils import author_name, author_email +from kallithea.lib.utils2 import credentials_filter, age as _age +from kallithea.model.db import User, ChangesetStatus age = lambda x, y=False: _age(x, y) capitalize = lambda x: x.capitalize() @@ -411,7 +425,7 @@ def show_id(cs): :param cs: changeset instance """ - from rhodecode import CONFIG + from kallithea import CONFIG def_len = safe_int(CONFIG.get('show_sha_length', 12)) show_rev = str2bool(CONFIG.get('show_revision_number', True)) @@ -454,7 +468,7 @@ def email_or_none(author): # extract email from the commit string _email = email(author) if _email != '': - # check it against RhodeCode database, and use the MAIN email for this + # check it against Kallithea database, and use the MAIN email for this # user user = User.get_by_email(_email, case_insensitive=True, cache=True) if user is not None: @@ -475,6 +489,10 @@ def person(author, show_attr="username_a # attr to return from fetched user person_getter = lambda usr: getattr(usr, show_attr) + # if author is already an instance use it for extraction + if isinstance(author, User): + return person_getter(author) + # Valid email in the attribute passed, see if they're in the system _email = email(author) if _email != '': @@ -512,6 +530,9 @@ def desc_stylize(value): :param value: """ + if not value: + return '' + value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]', '

', value) value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]', @@ -534,11 +555,9 @@ def boolicon(value): """ if value: - return HTML.tag('img', src=url("/images/icons/accept.png"), - alt=_('True')) + return HTML.tag('i', class_="icon-ok-sign") else: - return HTML.tag('img', src=url("/images/icons/cancel.png"), - alt=_('False')) + return HTML.tag('i', class_="icon-minus-sign") def action_parser(user_log, feed=False, parse_cs=False): @@ -722,51 +741,51 @@ def action_parser(user_log, feed=False, # action : translated str, callback(extractor), icon action_map = { 'user_deleted_repo': (_('[deleted] repository'), - None, 'database_delete.png'), + None, 'icon-trash'), 'user_created_repo': (_('[created] repository'), - None, 'database_add.png'), + None, 'icon-plus icon-plus-colored'), 'user_created_fork': (_('[created] repository as fork'), - None, 'arrow_divide.png'), + None, 'icon-code-fork'), 'user_forked_repo': (_('[forked] repository'), - get_fork_name, 'arrow_divide.png'), + get_fork_name, 'icon-code-fork'), 'user_updated_repo': (_('[updated] repository'), - None, 'database_edit.png'), + None, 'icon-pencil icon-pencil-colored'), 'user_downloaded_archive': (_('[downloaded] archive from repository'), - get_archive_name, 'page_white_compressed.png'), + get_archive_name, 'icon-download-alt'), 'admin_deleted_repo': (_('[delete] repository'), - None, 'database_delete.png'), + None, 'icon-trash'), 'admin_created_repo': (_('[created] repository'), - None, 'database_add.png'), + None, 'icon-plus icon-plus-colored'), 'admin_forked_repo': (_('[forked] repository'), - None, 'arrow_divide.png'), + None, 'icon-code-fork icon-fork-colored'), 'admin_updated_repo': (_('[updated] repository'), - None, 'database_edit.png'), + None, 'icon-pencil icon-pencil-colored'), 'admin_created_user': (_('[created] user'), - get_user_name, 'user_add.png'), + get_user_name, 'icon-user icon-user-colored'), 'admin_updated_user': (_('[updated] user'), - get_user_name, 'user_edit.png'), + get_user_name, 'icon-user icon-user-colored'), 'admin_created_users_group': (_('[created] user group'), - get_users_group, 'group_add.png'), + get_users_group, 'icon-pencil icon-pencil-colored'), 'admin_updated_users_group': (_('[updated] user group'), - get_users_group, 'group_edit.png'), + get_users_group, 'icon-pencil icon-pencil-colored'), 'user_commented_revision': (_('[commented] on revision in repository'), - get_cs_links, 'comment_add.png'), + get_cs_links, 'icon-comment icon-comment-colored'), 'user_commented_pull_request': (_('[commented] on pull request for'), - get_pull_request, 'comment_add.png'), + get_pull_request, 'icon-comment icon-comment-colored'), 'user_closed_pull_request': (_('[closed] pull request for'), - get_pull_request, 'tick.png'), + get_pull_request, 'icon-check'), 'push': (_('[pushed] into'), - get_cs_links, 'script_add.png'), - 'push_local': (_('[committed via RhodeCode] into repository'), - get_cs_links, 'script_edit.png'), + get_cs_links, 'icon-arrow-up'), + 'push_local': (_('[committed via Kallithea] into repository'), + get_cs_links, 'icon-pencil icon-pencil-colored'), 'push_remote': (_('[pulled from remote] into repository'), - get_cs_links, 'connect.png'), + get_cs_links, 'icon-arrow-up'), 'pull': (_('[pulled] from'), - None, 'down_16.png'), + None, 'icon-arrow-down'), 'started_following_repo': (_('[started following] repository'), - None, 'heart_add.png'), + None, 'icon-heart icon-heart-colored'), 'stopped_following_repo': (_('[stopped following] repository'), - None, 'heart_delete.png'), + None, 'icon-heart-empty icon-heart-colored'), } action_str = action_map.get(action, action) @@ -790,9 +809,9 @@ def action_parser(user_log, feed=False, if len(x) > 1: action, action_params = x - tmpl = """%s""" + tmpl = """""" ico = action_map.get(action, ['', '', ''])[2] - return literal(tmpl % ((url('/images/icons/')), ico, action)) + return literal(tmpl % (ico, action)) # returned callbacks we need to call to get return [lambda: literal(action), action_params_func, action_parser_icon] @@ -802,9 +821,9 @@ def action_parser(user_log, feed=False, #============================================================================== # PERMS #============================================================================== -from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \ -HasRepoPermissionAny, HasRepoPermissionAll, HasReposGroupPermissionAll, \ -HasReposGroupPermissionAny +from kallithea.lib.auth import HasPermissionAny, HasPermissionAll, \ +HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \ +HasRepoGroupPermissionAny #============================================================================== @@ -812,42 +831,36 @@ HasReposGroupPermissionAny #============================================================================== def gravatar_url(email_address, size=30, ssl_enabled=True): - from pylons import url # doh, we need to re-import url to mock it later - from rhodecode import CONFIG + # doh, we need to re-import those to mock it later + from pylons import url + from pylons import tmpl_context as c + + _def = 'anonymous@kallithea-scm.org' # default gravatar + _use_gravatar = c.visual.use_gravatar + _gravatar_url = c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL - _def = 'anonymous@rhodecode.org' # default gravatar - use_gravatar = str2bool(CONFIG.get('use_gravatar')) - alternative_gravatar_url = CONFIG.get('alternative_gravatar_url', '') email_address = email_address or _def - if not use_gravatar or not email_address or email_address == _def: + if isinstance(email_address, unicode): + #hashlib crashes on unicode items + email_address = safe_str(email_address) + + if not _use_gravatar or not email_address or email_address == _def: + # pick best matching size to one given in size param f = lambda a, l: min(l, key=lambda x: abs(x - a)) return url("/images/user%s.png" % f(size, [14, 16, 20, 24, 30])) - if use_gravatar and alternative_gravatar_url: - tmpl = alternative_gravatar_url + if _use_gravatar: + _md5 = lambda s: hashlib.md5(s).hexdigest() + + tmpl = _gravatar_url parsed_url = urlparse.urlparse(url.current(qualified=True)) tmpl = tmpl.replace('{email}', email_address)\ - .replace('{md5email}', hashlib.md5(email_address.lower()).hexdigest()) \ + .replace('{md5email}', _md5(email_address.lower())) \ .replace('{netloc}', parsed_url.netloc)\ .replace('{scheme}', parsed_url.scheme)\ - .replace('{size}', str(size)) + .replace('{size}', safe_str(size)) return tmpl - default = 'identicon' - baseurl_nossl = "http://www.gravatar.com/avatar/" - baseurl_ssl = "https://secure.gravatar.com/avatar/" - baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl - - if isinstance(email_address, unicode): - #hashlib crashes on unicode items - email_address = safe_str(email_address) - # construct the url - gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?" - gravatar_url += urllib.urlencode({'d': default, 's': str(size)}) - - return gravatar_url - - class Page(_Page): """ Custom pager to match rendering style with YUI paginator @@ -933,8 +946,9 @@ class Page(_Page): if self.page != self.last_page and rightmost_page < self.last_page: nav_items.append(self._pagerlink(self.last_page, self.last_page)) - ## prerender links - nav_items.append(literal('' % str(int(self.page)+1))) + #_page_link = url.current() + #nav_items.append(literal('' % (_page_link, str(int(self.page)+1)))) + #nav_items.append(literal('' % (_page_link, str(int(self.page)+1)))) return self.separator.join(nav_items) def pager(self, format='~2~', page_param='page', partial_param='partial', @@ -1119,7 +1133,7 @@ def fancy_file_stats(stats): :param stats: two element list of added/deleted lines of code """ - from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \ + from kallithea.lib.diffs import NEW_FILENODE, DEL_FILENODE, \ MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE def cgen(l_type, a_v, d_v): @@ -1288,7 +1302,7 @@ def urlify_commit(text_, repository=None newtext = urlify_text(newtext, safe=False) try: - from rhodecode import CONFIG + from kallithea import CONFIG conf = CONFIG # allow multiple issue servers to be used @@ -1407,6 +1421,6 @@ def not_mapped_error(repo_name): def ip_range(ip_addr): - from rhodecode.model.db import UserIpMap + from kallithea.model.db import UserIpMap s, e = UserIpMap._get_ip_range(ip_addr) return '%s - %s' % (s, e) diff --git a/rhodecode/lib/hooks.py b/kallithea/lib/hooks.py rename from rhodecode/lib/hooks.py rename to kallithea/lib/hooks.py --- a/rhodecode/lib/hooks.py +++ b/kallithea/lib/hooks.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.hooks - ~~~~~~~~~~~~~~~~~~~ - - Hooks runned by rhodecode - - :created_on: Aug 6, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,21 +11,32 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.hooks +~~~~~~~~~~~~~~~~~~~ + +Hooks runned by kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Aug 6, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import os import sys import time import binascii -import traceback -from inspect import isfunction -from rhodecode.lib.vcs.utils.hgcompat import nullrev, revrange -from rhodecode.lib import helpers as h -from rhodecode.lib.utils import action_logger -from rhodecode.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.compat import json -from rhodecode.lib.exceptions import HTTPLockedRC, UserCreationError -from rhodecode.lib.utils2 import safe_str, _extract_extras -from rhodecode.model.db import Repository, User +from kallithea.lib.vcs.utils.hgcompat import nullrev, revrange +from kallithea.lib import helpers as h +from kallithea.lib.utils import action_logger +from kallithea.lib.vcs.backends.base import EmptyChangeset +from kallithea.lib.exceptions import HTTPLockedRC, UserCreationError +from kallithea.lib.utils2 import safe_str, _extract_extras +from kallithea.model.db import Repository, User def _get_scm_size(alias, root_path): @@ -134,9 +134,9 @@ def log_pull_action(ui, repo, **kwargs): action = 'pull' action_logger(user, action, ex.repository, ex.ip, commit=True) # extension hook call - from rhodecode import EXTENSIONS + from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PULL_HOOK', None) - if isfunction(callback): + if callable(callback): kw = {} kw.update(ex) callback(**kw) @@ -165,8 +165,8 @@ def log_push_action(ui, repo, **kwargs): ex = _extract_extras() - action = ex.action + ':%s' - + action_tmpl = ex.action + ':%s' + revs = [] if ex.scm == 'hg': node = kwargs['node'] @@ -176,26 +176,25 @@ def log_push_action(ui, repo, **kwargs): if len(revs) == 0: return (nullrev, nullrev) - return (max(revs), min(revs)) + return max(revs), min(revs) else: - return (len(repo) - 1, 0) + return len(repo) - 1, 0 stop, start = get_revs(repo, [node + ':']) - h = binascii.hexlify - revs = [h(repo[r].node()) for r in xrange(start, stop + 1)] + _h = binascii.hexlify + revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)] elif ex.scm == 'git': revs = kwargs.get('_git_revs', []) if '_git_revs' in kwargs: kwargs.pop('_git_revs') - action = action % ','.join(revs) - + action = action_tmpl % ','.join(revs) action_logger(ex.username, action, ex.repository, ex.ip, commit=True) # extension hook call - from rhodecode import EXTENSIONS + from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) - if isfunction(callback): + if callable(callback): kw = {'pushed_revs': revs} kw.update(ex) callback(**kw) @@ -217,9 +216,7 @@ def log_push_action(ui, repo, **kwargs): def log_create_repository(repository_dict, created_by, **kwargs): """ - Post create repository Hook. This is a dummy function for admins to re-use - if needed. It's taken from rhodecode-extensions module and executed - if present + Post create repository Hook. :param repository: dict dump of repository object :param created_by: username who created repository @@ -240,9 +237,9 @@ def log_create_repository(repository_dic 'repo_name' """ - from rhodecode import EXTENSIONS + from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'CREATE_REPO_HOOK', None) - if isfunction(callback): + if callable(callback): kw = {} kw.update(repository_dict) kw.update({'created_by': created_by}) @@ -253,9 +250,10 @@ def log_create_repository(repository_dic def check_allowed_create_user(user_dict, created_by, **kwargs): - from rhodecode import EXTENSIONS + # pre create hooks + from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PRE_CREATE_USER_HOOK', None) - if isfunction(callback): + if callable(callback): allowed, reason = callback(created_by=created_by, **user_dict) if not allowed: raise UserCreationError(reason) @@ -263,9 +261,7 @@ def check_allowed_create_user(user_dict, def log_create_user(user_dict, created_by, **kwargs): """ - Post create user Hook. This is a dummy function for admins to re-use - if needed. It's taken from rhodecode-extensions module and executed - if present + Post create user Hook. :param user_dict: dict dump of user object @@ -292,9 +288,9 @@ def log_create_user(user_dict, created_b 'inherit_default_permissions' """ - from rhodecode import EXTENSIONS + from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'CREATE_USER_HOOK', None) - if isfunction(callback): + if callable(callback): return callback(created_by=created_by, **user_dict) return 0 @@ -302,9 +298,7 @@ def log_create_user(user_dict, created_b def log_delete_repository(repository_dict, deleted_by, **kwargs): """ - Post delete repository Hook. This is a dummy function for admins to re-use - if needed. It's taken from rhodecode-extensions module and executed - if present + Post delete repository Hook. :param repository: dict dump of repository object :param deleted_by: username who deleted the repository @@ -325,9 +319,9 @@ def log_delete_repository(repository_dic 'repo_name' """ - from rhodecode import EXTENSIONS + from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'DELETE_REPO_HOOK', None) - if isfunction(callback): + if callable(callback): kw = {} kw.update(repository_dict) kw.update({'deleted_by': deleted_by, @@ -340,9 +334,7 @@ def log_delete_repository(repository_dic def log_delete_user(user_dict, deleted_by, **kwargs): """ - Post delete user Hook. This is a dummy function for admins to re-use - if needed. It's taken from rhodecode-extensions module and executed - if present + Post delete user Hook. :param user_dict: dict dump of user object @@ -369,9 +361,9 @@ def log_delete_user(user_dict, deleted_b 'inherit_default_permissions' """ - from rhodecode import EXTENSIONS + from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'DELETE_USER_HOOK', None) - if isfunction(callback): + if callable(callback): return callback(deleted_by=deleted_by, **user_dict) return 0 @@ -396,15 +388,16 @@ def handle_git_receive(repo_path, revs, """ from paste.deploy import appconfig from sqlalchemy import engine_from_config - from rhodecode.config.environment import load_environment - from rhodecode.model import init_model - from rhodecode.model.db import RhodeCodeUi - from rhodecode.lib.utils import make_ui + from kallithea.config.environment import load_environment + from kallithea.model import init_model + from kallithea.model.db import Ui + from kallithea.lib.utils import make_ui extras = _extract_extras(env) path, ini_name = os.path.split(extras['config']) conf = appconfig('config:%s' % ini_name, relative_to=path) - load_environment(conf.global_conf, conf.local_conf) + load_environment(conf.global_conf, conf.local_conf, test_env=False, + test_index=False) engine = engine_from_config(conf, 'sqlalchemy.db1.') init_model(engine) @@ -431,8 +424,7 @@ def handle_git_receive(repo_path, revs, pre_push(baseui, repo) # if push hook is enabled via web interface - elif hook_type == 'post' and _hooks.get(RhodeCodeUi.HOOK_PUSH): - + elif hook_type == 'post' and _hooks.get(Ui.HOOK_PUSH): rev_data = [] for l in revs: old_rev, new_rev, ref = l.split(' ') @@ -445,10 +437,16 @@ def handle_git_receive(repo_path, revs, 'name': _ref_data[2].strip()}) git_revs = [] - for push_ref in rev_data: + + for push_ref in rev_data: _type = push_ref['type'] if _type == 'heads': if push_ref['old_rev'] == EmptyChangeset().raw_id: + # update the symbolic ref if we push new repo + if repo.is_empty(): + repo._repo.refs.set_symbolic_ref('HEAD', + 'refs/heads/%s' % push_ref['name']) + cmd = "for-each-ref --format='%(refname)' 'refs/heads/*'" heads = repo.run_git_command(cmd)[0] heads = heads.replace(push_ref['ref'], '') diff --git a/rhodecode/lib/indexers/__init__.py b/kallithea/lib/indexers/__init__.py rename from rhodecode/lib/indexers/__init__.py rename to kallithea/lib/indexers/__init__.py --- a/rhodecode/lib/indexers/__init__.py +++ b/kallithea/lib/indexers/__init__.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.indexers.__init__ - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Whoosh indexing module for RhodeCode - - :created_on: Aug 17, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,19 +11,33 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.indexers.__init__ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whoosh indexing module for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Aug 17, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import os import sys import logging from os.path import dirname as dn, join as jn -#to get the rhodecode import +# Add location of top level folder to sys.path sys.path.append(dn(dn(dn(os.path.realpath(__file__))))) from whoosh.analysis import RegexTokenizer, LowercaseFilter, StopFilter from whoosh.fields import TEXT, ID, STORED, NUMERIC, BOOLEAN, Schema, FieldType, DATETIME from whoosh.formats import Characters from whoosh.highlight import highlight as whoosh_highlight, HtmlFormatter, ContextFragmenter -from rhodecode.lib.utils2 import LazyProperty +from kallithea.lib.utils2 import LazyProperty log = logging.getLogger(__name__) @@ -144,7 +147,7 @@ class WhooshResultWrapper(object): res.update({'content_short': content_short, 'content_short_hl': self.highlight(content_short), 'f_path': f_path - }) + }) elif self.search_type == 'path': full_repo_path = jn(self.repo_location, res['repository']) f_path = res['path'].split(full_repo_path)[-1] diff --git a/rhodecode/lib/indexers/daemon.py b/kallithea/lib/indexers/daemon.py rename from rhodecode/lib/indexers/daemon.py rename to kallithea/lib/indexers/daemon.py --- a/rhodecode/lib/indexers/daemon.py +++ b/kallithea/lib/indexers/daemon.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.indexers.daemon - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - A daemon will read from task table and run tasks - - :created_on: Jan 26, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.indexers.daemon +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A daemon will read from task table and run tasks + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jan 26, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from __future__ import with_statement import os @@ -35,18 +38,18 @@ from time import mktime from os.path import dirname as dn from os.path import join as jn -#to get the rhodecode import +# Add location of top level folder to sys.path project_path = dn(dn(dn(dn(os.path.realpath(__file__))))) sys.path.append(project_path) -from rhodecode.config.conf import INDEX_EXTENSIONS -from rhodecode.model.scm import ScmModel -from rhodecode.model.db import Repository -from rhodecode.lib.utils2 import safe_unicode, safe_str -from rhodecode.lib.indexers import SCHEMA, IDX_NAME, CHGSETS_SCHEMA, \ +from kallithea.config.conf import INDEX_EXTENSIONS +from kallithea.model.scm import ScmModel +from kallithea.model.db import Repository +from kallithea.lib.utils2 import safe_unicode, safe_str +from kallithea.lib.indexers import SCHEMA, IDX_NAME, CHGSETS_SCHEMA, \ CHGSET_IDX_NAME -from rhodecode.lib.vcs.exceptions import ChangesetError, RepositoryError, \ +from kallithea.lib.vcs.exceptions import ChangesetError, RepositoryError, \ NodeDoesNotExistError from whoosh.index import create_in, open_dir, exists_in @@ -111,14 +114,16 @@ class WhooshIndexingDaemon(object): self.initial = False def _get_index_revision(self, repo): - db_repo = Repository.get_by_repo_name(repo.name) + db_repo = Repository.get_by_repo_name(repo.name_unicode) landing_rev = 'tip' if db_repo: - landing_rev = db_repo.landing_rev + _rev_type, _rev = db_repo.landing_rev + landing_rev = _rev return landing_rev - def _get_index_changeset(self, repo): - index_rev = self._get_index_revision(repo) + def _get_index_changeset(self, repo, index_rev=None): + if not index_rev: + index_rev = self._get_index_revision(repo) cs = repo.get_changeset(index_rev) return cs @@ -139,7 +144,7 @@ class WhooshIndexingDaemon(object): pass return index_paths_ - def get_node(self, repo, path): + def get_node(self, repo, path, index_rev=None): """ gets a filenode based on given full path.It operates on string for hg git compatability. @@ -150,20 +155,20 @@ class WhooshIndexingDaemon(object): """ root_path = safe_str(repo.path)+'/' parts = safe_str(path).partition(root_path) - cs = self._get_index_changeset(repo) + cs = self._get_index_changeset(repo, index_rev=index_rev) node = cs.get_node(parts[-1]) return node def get_node_mtime(self, node): return mktime(node.last_changeset.date.timetuple()) - def add_doc(self, writer, path, repo, repo_name): + def add_doc(self, writer, path, repo, repo_name, index_rev=None): """ Adding doc to writer this function itself fetches data from the instance of vcs backend """ - node = self.get_node(repo, path) + node = self.get_node(repo, path, index_rev) indexed = indexed_w_content = 0 # we just index the content of chosen files, and skip binary files if node.extension in INDEX_EXTENSIONS and not node.is_binary: @@ -249,8 +254,9 @@ class WhooshIndexingDaemon(object): i_cnt = iwc_cnt = 0 log.debug('building index for %s @revision:%s' % (repo.path, self._get_index_revision(repo))) + index_rev = self._get_index_revision(repo) for idx_path in self.get_paths(repo): - i, iwc = self.add_doc(file_idx_writer, idx_path, repo, repo_name) + i, iwc = self.add_doc(file_idx_writer, idx_path, repo, repo_name, index_rev) i_cnt += i iwc_cnt += iwc diff --git a/rhodecode/lib/ipaddr.py b/kallithea/lib/ipaddr.py rename from rhodecode/lib/ipaddr.py rename to kallithea/lib/ipaddr.py diff --git a/rhodecode/lib/markup_renderer.py b/kallithea/lib/markup_renderer.py rename from rhodecode/lib/markup_renderer.py rename to kallithea/lib/markup_renderer.py --- a/rhodecode/lib/markup_renderer.py +++ b/kallithea/lib/markup_renderer.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.markup_renderer - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - Renderer for markup languages with ability to parse using rst or markdown - - :created_on: Oct 27, 2011 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,12 +11,26 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.markup_renderer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Renderer for markup languages with ability to parse using rst or markdown + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Oct 27, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import re import logging import traceback -from rhodecode.lib.utils2 import safe_unicode, MENTIONS_REGEX +from kallithea.lib.utils2 import safe_unicode, MENTIONS_REGEX log = logging.getLogger(__name__) @@ -120,9 +122,11 @@ class MarkupRenderer(object): return readme_data @classmethod - def plain(cls, source): + def plain(cls, source, universal_newline=True): source = safe_unicode(source) - + if universal_newline: + newline = '\n' + source = newline.join(source.splitlines()) def urlify_text(text): url_pat = re.compile(r'(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]' '|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)') @@ -150,7 +154,8 @@ class MarkupRenderer(object): except Exception: log.error(traceback.format_exc()) if safe: - return source + log.debug('Fallbacking to render in plain mode') + return cls.plain(source) else: raise @@ -180,7 +185,8 @@ class MarkupRenderer(object): except Exception: log.error(traceback.format_exc()) if safe: - return source + log.debug('Fallbacking to render in plain mode') + return cls.plain(source) else: raise diff --git a/rhodecode/lib/middleware/__init__.py b/kallithea/lib/middleware/__init__.py rename from rhodecode/lib/middleware/__init__.py rename to kallithea/lib/middleware/__init__.py --- a/rhodecode/lib/middleware/__init__.py +++ b/kallithea/lib/middleware/__init__.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . diff --git a/rhodecode/lib/middleware/errormator.py b/kallithea/lib/middleware/errormator.py rename from rhodecode/lib/middleware/errormator.py rename to kallithea/lib/middleware/errormator.py --- a/rhodecode/lib/middleware/errormator.py +++ b/kallithea/lib/middleware/errormator.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.middleware.errormator - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - middleware to handle errormator publishing of errors - - :created_on: October 18, 2012 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.middleware.errormator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +middleware to handle errormator publishing of errors + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: October 18, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + try: from errormator_client import make_errormator_middleware diff --git a/rhodecode/lib/middleware/https_fixup.py b/kallithea/lib/middleware/https_fixup.py rename from rhodecode/lib/middleware/https_fixup.py rename to kallithea/lib/middleware/https_fixup.py --- a/rhodecode/lib/middleware/https_fixup.py +++ b/kallithea/lib/middleware/https_fixup.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.middleware.https_fixup - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - middleware to handle https correctly - - :created_on: May 23, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,8 +11,22 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.middleware.https_fixup +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -from rhodecode.lib.utils2 import str2bool +middleware to handle https correctly + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: May 23, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + + +from kallithea.lib.utils2 import str2bool class HttpsFixup(object): diff --git a/rhodecode/lib/middleware/pygrack.py b/kallithea/lib/middleware/pygrack.py rename from rhodecode/lib/middleware/pygrack.py rename to kallithea/lib/middleware/pygrack.py --- a/rhodecode/lib/middleware/pygrack.py +++ b/kallithea/lib/middleware/pygrack.py @@ -1,13 +1,12 @@ import os import socket import logging -import subprocess import traceback from webob import Request, Response, exc -import rhodecode -from rhodecode.lib.vcs import subprocessio +import kallithea +from kallithea.lib.vcs import subprocessio log = logging.getLogger(__name__) @@ -82,11 +81,11 @@ class GitRepository(object): # if you do add '\n' as part of data, count it. server_advert = '# service=%s' % git_command packet_len = str(hex(len(server_advert) + 4)[2:].rjust(4, '0')).lower() - _git_path = rhodecode.CONFIG.get('git_path', 'git') + _git_path = kallithea.CONFIG.get('git_path', 'git') try: out = subprocessio.SubprocessIOChunker( r'%s %s --stateless-rpc --advertise-refs "%s"' % ( - _git_path, git_command[4:], self.content_path), + _git_path, git_command[4:], self.content_path), starting_values=[ packet_len + server_advert + '0000' ] @@ -107,6 +106,7 @@ class GitRepository(object): returns an iterator obj with contents of git command's response to stdout """ + _git_path = kallithea.CONFIG.get('git_path', 'git') git_command = self._get_fixedpath(request.path_info) if git_command not in self.commands: log.debug('command %s not allowed' % git_command) @@ -124,10 +124,10 @@ class GitRepository(object): gitenv['GIT_CONFIG_NOGLOBAL'] = '1' opts = dict( env=gitenv, - cwd=os.getcwd() + cwd=self.content_path, ) - cmd = r'git %s --stateless-rpc "%s"' % (git_command[4:], - self.content_path), + cmd = r'%s %s --stateless-rpc "%s"' % (_git_path, git_command[4:], + self.content_path), log.debug('handling cmd %s' % cmd) out = subprocessio.SubprocessIOChunker( cmd, @@ -141,11 +141,11 @@ class GitRepository(object): if git_command in [u'git-receive-pack']: # updating refs manually after each push. # Needed for pre-1.7.0.4 git clients using regular HTTP mode. - _git_path = rhodecode.CONFIG.get('git_path', 'git') - cmd = (u'%s --git-dir "%s" ' - 'update-server-info' % (_git_path, self.content_path)) - log.debug('handling cmd %s' % cmd) - subprocess.call(cmd, shell=True) + from kallithea.lib.vcs import get_repo + from dulwich.server import update_server_info + repo = get_repo(self.content_path) + if repo: + update_server_info(repo._repo) resp = Response() resp.content_type = 'application/x-%s-result' % git_command.encode('utf8') @@ -197,4 +197,6 @@ class GitDirectory(object): def make_wsgi_app(repo_name, repo_root, extras): - return GitDirectory(repo_root, repo_name, extras) + from dulwich.web import LimitedInputFilter, GunzipFilter + app = GitDirectory(repo_root, repo_name, extras) + return GunzipFilter(LimitedInputFilter(app)) diff --git a/rhodecode/lib/middleware/sentry.py b/kallithea/lib/middleware/sentry.py rename from rhodecode/lib/middleware/sentry.py rename to kallithea/lib/middleware/sentry.py --- a/rhodecode/lib/middleware/sentry.py +++ b/kallithea/lib/middleware/sentry.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.middleware.sentry - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - middleware to handle sentry/raven publishing of errors - - :created_on: September 18, 2012 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.middleware.sentry +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +middleware to handle sentry/raven publishing of errors + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: September 18, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + try: from raven.base import Client diff --git a/rhodecode/lib/middleware/simplegit.py b/kallithea/lib/middleware/simplegit.py rename from rhodecode/lib/middleware/simplegit.py rename to kallithea/lib/middleware/simplegit.py --- a/rhodecode/lib/middleware/simplegit.py +++ b/kallithea/lib/middleware/simplegit.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.middleware.simplegit - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - SimpleGit middleware for handling git protocol request (push/clone etc.) - It's implemented with basic auth function - - :created_on: Apr 28, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,68 +11,40 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.middleware.simplegit +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +SimpleGit middleware for handling git protocol request (push/clone etc.) +It's implemented with basic auth function + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 28, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" + import os import re import logging import traceback -from dulwich import server as dulserver -from dulwich.web import LimitedInputFilter, GunzipFilter -from rhodecode.lib.exceptions import HTTPLockedRC -from rhodecode.lib.hooks import pre_pull - - -class SimpleGitUploadPackHandler(dulserver.UploadPackHandler): - - def handle(self): - write = lambda x: self.proto.write_sideband(1, x) - - graph_walker = dulserver.ProtocolGraphWalker(self, - self.repo.object_store, - self.repo.get_peeled) - objects_iter = self.repo.fetch_objects( - graph_walker.determine_wants, graph_walker, self.progress, - get_tagged=self.get_tagged) - - # Did the process short-circuit (e.g. in a stateless RPC call)? Note - # that the client still expects a 0-object pack in most cases. - if objects_iter is None: - return - - self.progress("counting objects: %d, done.\n" % len(objects_iter)) - dulserver.write_pack_objects(dulserver.ProtocolFile(None, write), - objects_iter) - messages = ['thank you for using rhodecode'] - - for msg in messages: - self.progress(msg + "\n") - # we are done - self.proto.write("0000") - - -dulserver.DEFAULT_HANDLERS = { - #git-ls-remote, git-clone, git-fetch and git-pull - 'git-upload-pack': SimpleGitUploadPackHandler, - #git-push - 'git-receive-pack': dulserver.ReceivePackHandler, -} - -# not used for now until dulwich gets fixed -#from dulwich.repo import Repo -#from dulwich.web import make_wsgi_chain - from paste.httpheaders import REMOTE_USER, AUTH_TYPE from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \ - HTTPBadRequest, HTTPNotAcceptable + HTTPNotAcceptable +from kallithea.model.db import User, Ui -from rhodecode.lib.utils2 import safe_str, fix_PATH, get_server_url,\ +from kallithea.lib.utils2 import safe_str, fix_PATH, get_server_url,\ _set_extras -from rhodecode.lib.base import BaseVCSController -from rhodecode.lib.auth import get_container_username -from rhodecode.lib.utils import is_valid_repo, make_ui -from rhodecode.lib.compat import json -from rhodecode.model.db import User, RhodeCodeUi +from kallithea.lib.base import BaseVCSController +from kallithea.lib.utils import make_ui, is_valid_repo +from kallithea.lib.exceptions import HTTPLockedRC +from kallithea.lib.hooks import pre_pull +from kallithea.lib import auth_modules log = logging.getLogger(__name__) @@ -139,28 +99,39 @@ class SimpleGit(BaseVCSController): if action in ['pull', 'push']: anonymous_user = self.__get_user('default') username = anonymous_user.username - anonymous_perm = self._check_permission(action, anonymous_user, - repo_name, ip_addr) + if anonymous_user.active: + # ONLY check permissions if the user is activated + anonymous_perm = self._check_permission(action, anonymous_user, + repo_name, ip_addr) + else: + anonymous_perm = False - if not anonymous_perm or not anonymous_user.active: + if not anonymous_user.active or not anonymous_perm: + if not anonymous_user.active: + log.debug('Anonymous access is disabled, running ' + 'authentication') + if not anonymous_perm: log.debug('Not enough credentials to access this ' 'repository as anonymous user') - if not anonymous_user.active: - log.debug('Anonymous access is disabled, running ' - 'authentication') + + username = None #============================================================== # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS #============================================================== - # Attempting to retrieve username from the container - username = get_container_username(environ, self.config) + # try to auth based on environ, container auth methods + log.debug('Running PRE-AUTH for container based authentication') + pre_auth = auth_modules.authenticate('', '', environ) + if pre_auth and pre_auth.get('username'): + username = pre_auth['username'] + log.debug('PRE-AUTH got %s as username' % username) # If not authenticated by the container, running basic auth if not username: self.authenticate.realm = \ - safe_str(self.config['rhodecode_realm']) + safe_str(self.config['realm']) result = self.authenticate(environ) if isinstance(result, str): AUTH_TYPE.update(environ, 'basic') @@ -187,8 +158,8 @@ class SimpleGit(BaseVCSController): return HTTPForbidden()(environ, start_response) # extras are injected into UI object and later available - # in hooks executed by rhodecode - from rhodecode import CONFIG + # in hooks executed by kallithea + from kallithea import CONFIG server_url = get_server_url(environ) extras = { 'ip': ip_addr, @@ -253,13 +224,12 @@ class SimpleGit(BaseVCSController): :param repo_path: full path to the repository """ - from rhodecode.lib.middleware.pygrack import make_wsgi_app + from kallithea.lib.middleware.pygrack import make_wsgi_app app = make_wsgi_app( repo_root=safe_str(self.basepath), repo_name=repo_name, extras=extras, ) - app = GunzipFilter(LimitedInputFilter(app)) return app def __get_repository(self, environ): @@ -307,13 +277,13 @@ class SimpleGit(BaseVCSController): """ Handles pull action, push is handled by post-receive hook """ - from rhodecode.lib.hooks import log_pull_action + from kallithea.lib.hooks import log_pull_action service = environ['QUERY_STRING'].split('=') if len(service) < 2: return - from rhodecode.model.db import Repository + from kallithea.model.db import Repository _repo = Repository.get_by_repo_name(repo_name) _repo = _repo.scm_instance @@ -321,7 +291,7 @@ class SimpleGit(BaseVCSController): if action == 'pull': # stupid git, emulate pre-pull hook ! pre_pull(ui=baseui, repo=_repo._repo) - if action == 'pull' and _hooks.get(RhodeCodeUi.HOOK_PULL): + if action == 'pull' and _hooks.get(Ui.HOOK_PULL): log_pull_action(ui=baseui, repo=_repo._repo) def __inject_extras(self, repo_path, baseui, extras={}): diff --git a/rhodecode/lib/middleware/simplehg.py b/kallithea/lib/middleware/simplehg.py rename from rhodecode/lib/middleware/simplehg.py rename to kallithea/lib/middleware/simplehg.py --- a/rhodecode/lib/middleware/simplehg.py +++ b/kallithea/lib/middleware/simplehg.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.middleware.simplehg - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - SimpleHG middleware for handling mercurial protocol request - (push/clone etc.). It's implemented with basic auth function - - :created_on: Apr 28, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,26 +11,39 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.middleware.simplehg +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +SimpleHG middleware for handling mercurial protocol request +(push/clone etc.). It's implemented with basic auth function + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 28, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" + import os import logging import traceback - from paste.httpheaders import REMOTE_USER, AUTH_TYPE from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \ - HTTPBadRequest, HTTPNotAcceptable + HTTPNotAcceptable +from kallithea.model.db import User -from rhodecode.lib.utils2 import safe_str, fix_PATH, get_server_url,\ +from kallithea.lib.utils2 import safe_str, fix_PATH, get_server_url,\ _set_extras -from rhodecode.lib.base import BaseVCSController -from rhodecode.lib.auth import get_container_username -from rhodecode.lib.utils import make_ui, is_valid_repo, ui_sections -from rhodecode.lib.compat import json -from rhodecode.lib.vcs.utils.hgcompat import RepoError, hgweb_mod -from rhodecode.model.db import User -from rhodecode.lib.exceptions import HTTPLockedRC - +from kallithea.lib.base import BaseVCSController +from kallithea.lib.utils import make_ui, is_valid_repo, ui_sections +from kallithea.lib.vcs.utils.hgcompat import RepoError, hgweb_mod +from kallithea.lib.exceptions import HTTPLockedRC +from kallithea.lib import auth_modules log = logging.getLogger(__name__) @@ -102,28 +103,39 @@ class SimpleHg(BaseVCSController): if action in ['pull', 'push']: anonymous_user = self.__get_user('default') username = anonymous_user.username - anonymous_perm = self._check_permission(action, anonymous_user, - repo_name, ip_addr) + if anonymous_user.active: + # ONLY check permissions if the user is activated + anonymous_perm = self._check_permission(action, anonymous_user, + repo_name, ip_addr) + else: + anonymous_perm = False - if not anonymous_perm or not anonymous_user.active: + if not anonymous_user.active or not anonymous_perm: + if not anonymous_user.active: + log.debug('Anonymous access is disabled, running ' + 'authentication') + if not anonymous_perm: log.debug('Not enough credentials to access this ' 'repository as anonymous user') - if not anonymous_user.active: - log.debug('Anonymous access is disabled, running ' - 'authentication') + + username = None #============================================================== # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS #============================================================== - # Attempting to retrieve username from the container - username = get_container_username(environ, self.config) + # try to auth based on environ, container auth methods + log.debug('Running PRE-AUTH for container based authentication') + pre_auth = auth_modules.authenticate('', '', environ) + if pre_auth and pre_auth.get('username'): + username = pre_auth['username'] + log.debug('PRE-AUTH got %s as username' % username) # If not authenticated by the container, running basic auth if not username: self.authenticate.realm = \ - safe_str(self.config['rhodecode_realm']) + safe_str(self.config['realm']) result = self.authenticate(environ) if isinstance(result, str): AUTH_TYPE.update(environ, 'basic') @@ -150,8 +162,8 @@ class SimpleHg(BaseVCSController): return HTTPForbidden()(environ, start_response) # extras are injected into mercurial UI object and later available - # in hg hooks executed by rhodecode - from rhodecode import CONFIG + # in hg hooks executed by kallithea + from kallithea import CONFIG server_url = get_server_url(environ) extras = { 'ip': ip_addr, diff --git a/rhodecode/lib/middleware/wrapper.py b/kallithea/lib/middleware/wrapper.py rename from rhodecode/lib/middleware/wrapper.py rename to kallithea/lib/middleware/wrapper.py --- a/rhodecode/lib/middleware/wrapper.py +++ b/kallithea/lib/middleware/wrapper.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.middleware.wrapper - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - request time mesuring app - - :created_on: May 23, 2013 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,10 +11,24 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.middleware.wrapper +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +request time mesuring app + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: May 23, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import time import logging -from rhodecode.lib.base import _get_ip_addr, _get_access_path -from rhodecode.lib.utils2 import safe_unicode +from kallithea.lib.base import _get_ip_addr, _get_access_path +from kallithea.lib.utils2 import safe_unicode class RequestWrapper(object): @@ -39,7 +42,7 @@ class RequestWrapper(object): try: return self.application(environ, start_response) finally: - log = logging.getLogger('rhodecode.' + self.__class__.__name__) + log = logging.getLogger('kallithea.' + self.__class__.__name__) log.info('IP: %s Request to %s time: %.3fs' % ( _get_ip_addr(environ), safe_unicode(_get_access_path(environ)), time.time() - start) diff --git a/rhodecode/lib/paster_commands/__init__.py b/kallithea/lib/paster_commands/__init__.py rename from rhodecode/lib/paster_commands/__init__.py rename to kallithea/lib/paster_commands/__init__.py --- a/rhodecode/lib/paster_commands/__init__.py +++ b/kallithea/lib/paster_commands/__init__.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . diff --git a/rhodecode/lib/paster_commands/cache_keys.py b/kallithea/lib/paster_commands/cache_keys.py rename from rhodecode/lib/paster_commands/cache_keys.py rename to kallithea/lib/paster_commands/cache_keys.py --- a/rhodecode/lib/paster_commands/cache_keys.py +++ b/kallithea/lib/paster_commands/cache_keys.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.paster_commands.cache_keys - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - cleanup-keys paster command for RhodeCode - - - :created_on: mar 27, 2013 - :author: marcink - :copyright: (C) 2010-2013 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,17 +11,32 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.paster_commands.cache_keys +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +cleanup-keys paster command for Kallithea + + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: mar 27, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from __future__ import with_statement import os import sys import logging -from rhodecode.model.meta import Session -from rhodecode.lib.utils import BasePasterCommand -from rhodecode.model.db import CacheInvalidation +from kallithea.model.meta import Session +from kallithea.lib.utils import BasePasterCommand +from kallithea.model.db import CacheInvalidation -# fix rhodecode import +# Add location of top level folder to sys.path from os.path import dirname as dn rc_path = dn(dn(dn(os.path.realpath(__file__)))) sys.path.append(rc_path) @@ -47,7 +50,7 @@ class Command(BasePasterCommand): min_args = 1 usage = "CONFIG_FILE" - group_name = "RhodeCode" + group_name = "Kallithea" takes_config_file = -1 parser = BasePasterCommand.standard_parser(verbose=True) summary = "Cache keys utils" diff --git a/rhodecode/lib/paster_commands/ishell.py b/kallithea/lib/paster_commands/ishell.py rename from rhodecode/lib/paster_commands/ishell.py rename to kallithea/lib/paster_commands/ishell.py --- a/rhodecode/lib/paster_commands/ishell.py +++ b/kallithea/lib/paster_commands/ishell.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.paster_commands.ishell - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - interactive shell paster command for RhodeCode - - - :created_on: Apr 4, 2013 - :author: marcink - :copyright: (C) 2010-2013 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,15 +11,29 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.paster_commands.ishell +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +interactive shell paster command for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 4, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from __future__ import with_statement import os import sys import logging -from rhodecode.lib.utils import BasePasterCommand +from kallithea.lib.utils import BasePasterCommand -# fix rhodecode import +# Add location of top level folder to sys.path from os.path import dirname as dn rc_path = dn(dn(dn(os.path.realpath(__file__)))) sys.path.append(rc_path) @@ -45,7 +47,7 @@ class Command(BasePasterCommand): min_args = 1 usage = "CONFIG_FILE" - group_name = "RhodeCode" + group_name = "Kallithea" takes_config_file = -1 parser = BasePasterCommand.standard_parser(verbose=True) summary = "Interactive shell" @@ -60,14 +62,14 @@ class Command(BasePasterCommand): import time import shutil import datetime - from rhodecode.model.db import * + from kallithea.model.db import * try: from IPython import embed from IPython.config.loader import Config cfg = Config() cfg.InteractiveShellEmbed.confirm_exit = False - embed(config=cfg, banner1="RhodeCode IShell.") + embed(config=cfg, banner1="Kallithea IShell.") except ImportError: print 'ipython installation required for ishell' sys.exit(-1) diff --git a/rhodecode/lib/paster_commands/make_index.py b/kallithea/lib/paster_commands/make_index.py rename from rhodecode/lib/paster_commands/make_index.py rename to kallithea/lib/paster_commands/make_index.py --- a/rhodecode/lib/paster_commands/make_index.py +++ b/kallithea/lib/paster_commands/make_index.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.paster_commands.make_index - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - make-index paster command for RhodeCode - - :created_on: Aug 17, 2010 - :author: marcink - :copyright: (C) 2010-2013 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,19 +11,34 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.paster_commands.make_index +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +make-index paster command for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Aug 17, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" + from __future__ import with_statement import os import sys import logging -from rhodecode.lib.utils import BasePasterCommand +from kallithea.lib.utils import BasePasterCommand from string import strip from shutil import rmtree -from rhodecode.model.repo import RepoModel -from rhodecode.lib.utils import BasePasterCommand, load_rcextensions +from kallithea.model.repo import RepoModel +from kallithea.lib.utils import BasePasterCommand, load_rcextensions -# fix rhodecode import +# Add location of top level folder to sys.path from os.path import dirname as dn rc_path = dn(dn(dn(os.path.realpath(__file__)))) sys.path.append(rc_path) @@ -46,7 +50,7 @@ class Command(BasePasterCommand): min_args = 1 usage = "CONFIG_FILE" - group_name = "RhodeCode" + group_name = "Kallithea" takes_config_file = -1 parser = BasePasterCommand.standard_parser(verbose=True) summary = "Creates or updates full text search index" @@ -70,8 +74,8 @@ class Command(BasePasterCommand): #====================================================================== # WHOOSH DAEMON #====================================================================== - from rhodecode.lib.pidlock import LockHeld, DaemonLock - from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon + from kallithea.lib.pidlock import LockHeld, DaemonLock + from kallithea.lib.indexers.daemon import WhooshIndexingDaemon try: l = DaemonLock(file_=os.path.join(dn(dn(index_location)), 'make_index.lock')) diff --git a/rhodecode/lib/paster_commands/make_rcextensions.py b/kallithea/lib/paster_commands/make_rcextensions.py rename from rhodecode/lib/paster_commands/make_rcextensions.py rename to kallithea/lib/paster_commands/make_rcextensions.py --- a/rhodecode/lib/paster_commands/make_rcextensions.py +++ b/kallithea/lib/paster_commands/make_rcextensions.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.paster_commands.make_rcextensions - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - make-rcext paster command for RhodeCode - - :created_on: Mar 6, 2012 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.paster_commands.make_rcextensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +make-rcext paster command for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Mar 6, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" + from __future__ import with_statement import os @@ -29,9 +33,9 @@ import sys import logging import pkg_resources -from rhodecode.lib.utils import BasePasterCommand, ask_ok +from kallithea.lib.utils import BasePasterCommand, ask_ok -# fix rhodecode import +# Add location of top level folder to sys.path from os.path import dirname as dn rc_path = dn(dn(dn(os.path.realpath(__file__)))) sys.path.append(rc_path) @@ -45,10 +49,10 @@ class Command(BasePasterCommand): min_args = 1 usage = "CONFIG_FILE" - group_name = "RhodeCode" + group_name = "Kallithea" takes_config_file = -1 parser = BasePasterCommand.standard_parser(verbose=True) - summary = "Creates additional extensions for rhodecode" + summary = "Creates additional extensions for kallithea" def command(self): logging.config.fileConfig(self.path_to_ini_file) @@ -64,7 +68,7 @@ class Command(BasePasterCommand): here = config['here'] tmpl = pkg_resources.resource_string( - 'rhodecode', os.path.join('config', 'rcextensions', '__init__.py') + 'kallithea', os.path.join('config', 'rcextensions', '__init__.py') ) ext_file = os.path.join(here, 'rcextensions', '__init__.py') if os.path.exists(ext_file): diff --git a/rhodecode/lib/paster_commands/repo_scan.py b/kallithea/lib/paster_commands/repo_scan.py rename from rhodecode/lib/paster_commands/repo_scan.py rename to kallithea/lib/paster_commands/repo_scan.py --- a/rhodecode/lib/paster_commands/repo_scan.py +++ b/kallithea/lib/paster_commands/repo_scan.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.paster_commands.make_rcextensions - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - repo-scan paster command for RhodeCode - - - :created_on: Feb 9, 2013 - :author: marcink - :copyright: (C) 2010-2013 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,16 +11,30 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.paster_commands.make_rcextensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +repo-scan paster command for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Feb 9, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from __future__ import with_statement import os import sys import logging -from rhodecode.model.scm import ScmModel -from rhodecode.lib.utils import BasePasterCommand, repo2db_mapper +from kallithea.model.scm import ScmModel +from kallithea.lib.utils import BasePasterCommand, repo2db_mapper -# fix rhodecode import +# Add location of top level folder to sys.path from os.path import dirname as dn rc_path = dn(dn(dn(os.path.realpath(__file__)))) sys.path.append(rc_path) @@ -46,7 +48,7 @@ class Command(BasePasterCommand): min_args = 1 usage = "CONFIG_FILE" - group_name = "RhodeCode" + group_name = "Kallithea" takes_config_file = -1 parser = BasePasterCommand.standard_parser(verbose=True) summary = "Rescan default location for new repositories" @@ -67,5 +69,5 @@ class Command(BasePasterCommand): '--delete-obsolete', action='store_true', help="Use this flag do delete repositories that are " - "present in RhodeCode database but not on the filesystem", + "present in Kallithea database but not on the filesystem", ) diff --git a/rhodecode/lib/paster_commands/setup_rhodecode.py b/kallithea/lib/paster_commands/setup_db.py rename from rhodecode/lib/paster_commands/setup_rhodecode.py rename to kallithea/lib/paster_commands/setup_db.py --- a/rhodecode/lib/paster_commands/setup_rhodecode.py +++ b/kallithea/lib/paster_commands/setup_db.py @@ -4,7 +4,7 @@ from paste.script.appinstall import Abst from paste.script.command import BadCommand from paste.deploy import appconfig -# fix rhodecode import +# Add location of top level folder to sys.path from os.path import dirname as dn rc_path = dn(dn(dn(os.path.realpath(__file__)))) sys.path.append(rc_path) @@ -17,11 +17,11 @@ class Command(AbstractInstallCommand): min_args = 1 summary = "Setup an application, given a config file" usage = "CONFIG_FILE" - group_name = "RhodeCode" + group_name = "Kallithea" description = """\ - Setup RhodeCode according to its configuration file. This is + Setup Kallithea according to its configuration file. This is the second part of a two-phase web application installation process (the first phase is prepare-app). The setup process consist of things like setting up databases, creating super user diff --git a/rhodecode/lib/paster_commands/update_repoinfo.py b/kallithea/lib/paster_commands/update_repoinfo.py rename from rhodecode/lib/paster_commands/update_repoinfo.py rename to kallithea/lib/paster_commands/update_repoinfo.py --- a/rhodecode/lib/paster_commands/update_repoinfo.py +++ b/kallithea/lib/paster_commands/update_repoinfo.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.paster_commands.make_rcextensions - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - uodate-repoinfo paster command for RhodeCode - - :created_on: Jul 14, 2012 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.paster_commands.make_rcextensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +uodate-repoinfo paster command for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jul 14, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from __future__ import with_statement import os @@ -29,12 +32,12 @@ import sys import logging import string -from rhodecode.lib.utils import BasePasterCommand -from rhodecode.model.db import Repository -from rhodecode.model.repo import RepoModel -from rhodecode.model.meta import Session +from kallithea.lib.utils import BasePasterCommand +from kallithea.model.db import Repository +from kallithea.model.repo import RepoModel +from kallithea.model.meta import Session -# fix rhodecode import +# Add location of top level folder to sys.path from os.path import dirname as dn rc_path = dn(dn(dn(os.path.realpath(__file__)))) sys.path.append(rc_path) @@ -48,7 +51,7 @@ class Command(BasePasterCommand): min_args = 1 usage = "CONFIG_FILE" - group_name = "RhodeCode" + group_name = "Kallithea" takes_config_file = -1 parser = BasePasterCommand.standard_parser(verbose=True) summary = "Updates repositories caches for last changeset" diff --git a/rhodecode/lib/pidlock.py b/kallithea/lib/pidlock.py rename from rhodecode/lib/pidlock.py rename to kallithea/lib/pidlock.py --- a/rhodecode/lib/pidlock.py +++ b/kallithea/lib/pidlock.py @@ -1,12 +1,24 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import with_statement import os -import sys -import time import errno -from warnings import warn from multiprocessing.util import Finalize -from rhodecode.lib.compat import kill +from kallithea.lib.compat import kill class LockHeld(Exception): @@ -27,9 +39,8 @@ class DaemonLock(object): def __init__(self, file_=None, callbackfn=None, desc='daemon lock', debug=False): - self.pidfile = file_ if file_ else os.path.join( - os.path.dirname(__file__), - 'running.lock') + lock_name = os.path.join(os.path.dirname(__file__), 'running.lock') + self.pidfile = file_ if file_ else lock_name self.callbackfn = callbackfn self.desc = desc self.debug = debug @@ -37,7 +48,7 @@ class DaemonLock(object): #run the lock automatically ! self.lock() self._finalize = Finalize(self, DaemonLock._on_finalize, - args=(self, debug), exitpriority=10) + args=(self, debug), exitpriority=10) @staticmethod def _on_finalize(lock, debug): @@ -63,15 +74,15 @@ class DaemonLock(object): if self.debug: print 'checking for already running process' try: - pidfile = open(self.pidfile, "r") - pidfile.seek(0) - running_pid = int(pidfile.readline()) - - pidfile.close() + with open(self.pidfile, 'r') as f: + try: + running_pid = int(f.readline()) + except ValueError: + running_pid = -1 if self.debug: print ('lock file present running_pid: %s, ' - 'checking for execution') % running_pid + 'checking for execution' % (running_pid,)) # Now we check the PID from lock file matches to the current # process PID if running_pid: @@ -128,7 +139,6 @@ class DaemonLock(object): dir_, file_ = os.path.split(pidfile) if not os.path.isdir(dir_): os.makedirs(dir_) - pidfile = open(self.pidfile, "wb") - pidfile.write(lockname) - pidfile.close + with open(self.pidfile, 'wb') as f: + f.write(lockname) self.held = True diff --git a/rhodecode/lib/profiler.py b/kallithea/lib/profiler.py rename from rhodecode/lib/profiler.py rename to kallithea/lib/profiler.py diff --git a/rhodecode/lib/rcmail/__init__.py b/kallithea/lib/rcmail/__init__.py rename from rhodecode/lib/rcmail/__init__.py rename to kallithea/lib/rcmail/__init__.py diff --git a/rhodecode/lib/rcmail/exceptions.py b/kallithea/lib/rcmail/exceptions.py rename from rhodecode/lib/rcmail/exceptions.py rename to kallithea/lib/rcmail/exceptions.py diff --git a/rhodecode/lib/rcmail/message.py b/kallithea/lib/rcmail/message.py rename from rhodecode/lib/rcmail/message.py rename to kallithea/lib/rcmail/message.py --- a/rhodecode/lib/rcmail/message.py +++ b/kallithea/lib/rcmail/message.py @@ -1,7 +1,7 @@ -from rhodecode.lib.rcmail.response import MailResponse +from kallithea.lib.rcmail.response import MailResponse -from rhodecode.lib.rcmail.exceptions import BadHeaders -from rhodecode.lib.rcmail.exceptions import InvalidMessage +from kallithea.lib.rcmail.exceptions import BadHeaders +from kallithea.lib.rcmail.exceptions import InvalidMessage class Attachment(object): diff --git a/rhodecode/lib/rcmail/response.py b/kallithea/lib/rcmail/response.py rename from rhodecode/lib/rcmail/response.py rename to kallithea/lib/rcmail/response.py diff --git a/rhodecode/lib/rcmail/smtp_mailer.py b/kallithea/lib/rcmail/smtp_mailer.py rename from rhodecode/lib/rcmail/smtp_mailer.py rename to kallithea/lib/rcmail/smtp_mailer.py --- a/rhodecode/lib/rcmail/smtp_mailer.py +++ b/kallithea/lib/rcmail/smtp_mailer.py @@ -1,14 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.rcmail.smtp_mailer - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Simple smtp mailer used in RhodeCode - - :created_on: Sep 13, 2010 - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -21,13 +11,27 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.rcmail.smtp_mailer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Simple smtp mailer used in Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Sep 13, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import time import logging import smtplib from socket import sslerror from email.utils import formatdate -from rhodecode.lib.rcmail.message import Message -from rhodecode.lib.rcmail.utils import DNS_NAME +from kallithea.lib.rcmail.message import Message +from kallithea.lib.rcmail.utils import DNS_NAME class SmtpMailer(object): diff --git a/rhodecode/lib/rcmail/utils.py b/kallithea/lib/rcmail/utils.py rename from rhodecode/lib/rcmail/utils.py rename to kallithea/lib/rcmail/utils.py diff --git a/kallithea/lib/recaptcha.py b/kallithea/lib/recaptcha.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/recaptcha.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +import urllib +import urllib2 + +API_SSL_SERVER = "https://www.google.com/recaptcha/api" +API_SERVER = "http://www.google.com/recaptcha/api" +VERIFY_SERVER = "www.google.com" + + +class RecaptchaResponse(object): + def __init__(self, is_valid, error_code=None): + self.is_valid = is_valid + self.error_code = error_code + + def __repr__(self): + return '' % (self.is_valid) + + +def displayhtml(public_key, use_ssl=False, error=None): + """Gets the HTML to display for reCAPTCHA + + public_key -- The public api key + use_ssl -- Should the request be sent over ssl? + error -- An error message to display (from RecaptchaResponse.error_code)""" + + error_param = '' + if error: + error_param = '&error=%s' % error + + if use_ssl: + server = API_SSL_SERVER + else: + server = API_SERVER + + return """ + + +""" % { + 'ApiServer': server, + 'PublicKey': public_key, + 'ErrorParam': error_param, + } + + +def submit(recaptcha_challenge_field, recaptcha_response_field, private_key, + remoteip): + """ + Submits a reCAPTCHA request for verification. Returns RecaptchaResponse + for the request + + recaptcha_challenge_field -- The value of recaptcha_challenge_field from the form + recaptcha_response_field -- The value of recaptcha_response_field from the form + private_key -- your reCAPTCHA private key + remoteip -- the user's ip address + """ + + if not (recaptcha_response_field and recaptcha_challenge_field and + len(recaptcha_response_field) and len( + recaptcha_challenge_field)): + return RecaptchaResponse(is_valid=False, + error_code='incorrect-captcha-sol') + + def encode_if_necessary(s): + if isinstance(s, unicode): + return s.encode('utf-8') + return s + + params = urllib.urlencode({ + 'privatekey': encode_if_necessary(private_key), + 'remoteip': encode_if_necessary(remoteip), + 'challenge': encode_if_necessary(recaptcha_challenge_field), + 'response': encode_if_necessary(recaptcha_response_field), + }) + + request = urllib2.Request( + url="http://%s/recaptcha/api/verify" % VERIFY_SERVER, + data=params, + headers={ + "Content-type": "application/x-www-form-urlencoded", + "User-agent": "reCAPTCHA Python" + } + ) + + httpresp = urllib2.urlopen(request) + + return_values = httpresp.read().splitlines() + httpresp.close() + + return_code = return_values[0] + + if return_code == "true": + return RecaptchaResponse(is_valid=True) + else: + return RecaptchaResponse(is_valid=False, error_code=return_values[1]) diff --git a/rhodecode/lib/timerproxy.py b/kallithea/lib/timerproxy.py rename from rhodecode/lib/timerproxy.py rename to kallithea/lib/timerproxy.py --- a/rhodecode/lib/timerproxy.py +++ b/kallithea/lib/timerproxy.py @@ -1,6 +1,21 @@ -from sqlalchemy.interfaces import ConnectionProxy +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + import time import logging +from sqlalchemy.interfaces import ConnectionProxy + log = logging.getLogger('timerproxy') BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38) diff --git a/rhodecode/lib/utils.py b/kallithea/lib/utils.py rename from rhodecode/lib/utils.py rename to kallithea/lib/utils.py --- a/rhodecode/lib/utils.py +++ b/kallithea/lib/utils.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.utils - ~~~~~~~~~~~~~~~~~~~ - - Utilities library for RhodeCode - - :created_on: Apr 18, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.utils +~~~~~~~~~~~~~~~~~~~ + +Utilities library for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 18, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import os import re @@ -40,24 +42,25 @@ from os.path import dirname as dn, join from paste.script.command import Command, BadCommand from webhelpers.text import collapse, remove_formatting, strip_tags +from beaker.cache import _cache_decorate -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.backends.base import BaseChangeset -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.utils.hgcompat import ui, config -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.backends.base import BaseChangeset +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.utils.hgcompat import ui, config +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError -from rhodecode.lib.caching_query import FromCache +from kallithea.lib.caching_query import FromCache -from rhodecode.model import meta -from rhodecode.model.db import Repository, User, RhodeCodeUi, \ - UserLog, RepoGroup, RhodeCodeSetting, CacheInvalidation, UserGroup -from rhodecode.model.meta import Session -from rhodecode.model.repos_group import ReposGroupModel -from rhodecode.lib.utils2 import safe_str, safe_unicode, get_current_rhodecode_user -from rhodecode.lib.vcs.utils.fakemod import create_module -from rhodecode.model.users_group import UserGroupModel +from kallithea.model import meta +from kallithea.model.db import Repository, User, Ui, \ + UserLog, RepoGroup, Setting, CacheInvalidation, UserGroup +from kallithea.model.meta import Session +from kallithea.model.repo_group import RepoGroupModel +from kallithea.lib.utils2 import safe_str, safe_unicode, get_current_authuser +from kallithea.lib.vcs.utils.fakemod import create_module +from kallithea.model.user_group import UserGroupModel log = logging.getLogger(__name__) @@ -110,7 +113,7 @@ def get_repo_slug(request): return _repo -def get_repos_group_slug(request): +def get_repo_group_slug(request): _group = request.environ['pylons.routes_dict'].get('group_name') if _group: _group = _group.rstrip('/') @@ -131,6 +134,32 @@ def get_user_group_slug(request): return _group +def _extract_id_from_repo_name(repo_name): + if repo_name.startswith('/'): + repo_name = repo_name.lstrip('/') + by_id_match = re.match(r'^_(\d{1,})', repo_name) + if by_id_match: + return by_id_match.groups()[0] + + +def get_repo_by_id(repo_name): + """ + Extracts repo_name by id from special urls. Example url is _11/repo_name + + :param repo_name: + :return: repo_name if matched else None + """ + try: + _repo_id = _extract_id_from_repo_name(repo_name) + if _repo_id: + from kallithea.model.db import Repository + return Repository.get(_repo_id).repo_name + except Exception: + log.debug('Failed to extract repo_name from URL %s' % ( + traceback.format_exc())) + return + + def action_logger(user, action, repo, ipaddr='', sa=None, commit=False): """ Action logger for various actions made by users @@ -151,17 +180,17 @@ def action_logger(user, action, repo, ip # if we don't get explicit IP address try to get one from registered user # in tmpl context var if not ipaddr: - ipaddr = getattr(get_current_rhodecode_user(), 'ip_addr', '') + ipaddr = getattr(get_current_authuser(), 'ip_addr', '') try: - if hasattr(user, 'user_id'): + if getattr(user, 'user_id', None): user_obj = User.get(user.user_id) elif isinstance(user, basestring): user_obj = User.get_by_username(user) else: raise Exception('You have to provide a user object or a username') - if hasattr(repo, 'repo_id'): + if getattr(repo, 'repo_id', None): repo_obj = Repository.get(repo.repo_id) repo_name = repo_obj.repo_name elif isinstance(repo, basestring): @@ -261,17 +290,17 @@ def is_valid_repo(repo_name, base_path, return False -def is_valid_repos_group(repos_group_name, base_path, skip_path_check=False): +def is_valid_repo_group(repo_group_name, base_path, skip_path_check=False): """ Returns True if given path is a repository group False otherwise :param repo_name: :param base_path: """ - full_path = os.path.join(safe_str(base_path), safe_str(repos_group_name)) + full_path = os.path.join(safe_str(base_path), safe_str(repo_group_name)) # check if it's not a repo - if is_valid_repo(repos_group_name, base_path): + if is_valid_repo(repo_group_name, base_path): return False try: @@ -346,7 +375,7 @@ def make_ui(read_from='file', path=None, elif read_from == 'db': sa = meta.Session() - ret = sa.query(RhodeCodeUi)\ + ret = sa.query(Ui)\ .options(FromCache("sql_cache_short", "get_hg_ui_settings"))\ .all() @@ -358,7 +387,7 @@ def make_ui(read_from='file', path=None, baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key), safe_str(ui_.ui_value)) if ui_.ui_key == 'push_ssl': - # force set push_ssl requirement to False, rhodecode + # force set push_ssl requirement to False, kallithea # handles that baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key), False) @@ -367,13 +396,13 @@ def make_ui(read_from='file', path=None, return baseui -def set_rhodecode_config(config): +def set_app_settings(config): """ Updates pylons config with new settings from database :param config: """ - hgsettings = RhodeCodeSetting.get_app_settings() + hgsettings = Setting.get_app_settings() for k, v in hgsettings.items(): config[k] = v @@ -381,16 +410,16 @@ def set_rhodecode_config(config): def set_vcs_config(config): """ - Patch VCS config with some RhodeCode specific stuff + Patch VCS config with some Kallithea specific stuff - :param config: rhodecode.CONFIG + :param config: kallithea.CONFIG """ - import rhodecode - from rhodecode.lib.vcs import conf - from rhodecode.lib.utils2 import aslist + import kallithea + from kallithea.lib.vcs import conf + from kallithea.lib.utils2 import aslist conf.settings.BACKENDS = { - 'hg': 'rhodecode.lib.vcs.backends.hg.MercurialRepository', - 'git': 'rhodecode.lib.vcs.backends.git.GitRepository', + 'hg': 'kallithea.lib.vcs.backends.hg.MercurialRepository', + 'git': 'kallithea.lib.vcs.backends.git.GitRepository', } conf.settings.GIT_EXECUTABLE_PATH = config.get('git_path', 'git') @@ -414,7 +443,7 @@ def map_groups(path): # last element is repo in nested groups structure groups = groups[:-1] - rgm = ReposGroupModel(sa) + rgm = RepoGroupModel(sa) owner = User.get_first_admin() for lvl, group_name in enumerate(groups): group_name = '/'.join(groups[:lvl] + [group_name]) @@ -452,15 +481,15 @@ def repo2db_mapper(initial_repo_list, re :param install_git_hook: if this is True, also check and install githook for a repo if missing """ - from rhodecode.model.repo import RepoModel - from rhodecode.model.scm import ScmModel + from kallithea.model.repo import RepoModel + from kallithea.model.scm import ScmModel sa = meta.Session() - rm = RepoModel() + repo_model = RepoModel() user = User.get_first_admin() added = [] ##creation defaults - defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True) + defs = Setting.get_default_repo_settings(strip_prefix=True) enable_statistics = defs.get('repo_enable_statistics') enable_locking = defs.get('repo_enable_locking') enable_downloads = defs.get('repo_enable_downloads') @@ -468,8 +497,9 @@ def repo2db_mapper(initial_repo_list, re for name, repo in initial_repo_list.items(): group = map_groups(name) - db_repo = rm.get_by_repo_name(name) - # found repo that is on filesystem not in RhodeCode database + unicode_name = safe_unicode(name) + db_repo = repo_model.get_by_repo_name(unicode_name) + # found repo that is on filesystem not in Kallithea database if not db_repo: log.info('repository %s not found, creating now' % name) added.append(name) @@ -477,28 +507,32 @@ def repo2db_mapper(initial_repo_list, re if repo.description != 'unknown' else '%s repository' % name) - new_repo = rm.create_repo( + new_repo = repo_model._create_repo( repo_name=name, repo_type=repo.alias, description=desc, - repos_group=getattr(group, 'group_id', None), + repo_group=getattr(group, 'group_id', None), owner=user, - just_db=True, enable_locking=enable_locking, enable_downloads=enable_downloads, enable_statistics=enable_statistics, - private=private + private=private, + state=Repository.STATE_CREATED ) + sa.commit() # we added that repo just now, and make sure it has githook - # installed + # installed, and updated server info if new_repo.repo_type == 'git': - ScmModel().install_git_hook(new_repo.scm_instance) + git_repo = new_repo.scm_instance + ScmModel().install_git_hook(git_repo) + # update repository server-info + log.debug('Running update server info') + git_repo._update_server_info() new_repo.update_changeset_cache() elif install_git_hook: if db_repo.repo_type == 'git': ScmModel().install_git_hook(db_repo.scm_instance) - sa.commit() removed = [] if remove_obsolete: # remove from database those repositories that are not in the filesystem @@ -546,13 +580,13 @@ def add_cache(settings): def load_rcextensions(root_path): - import rhodecode - from rhodecode.config import conf + import kallithea + from kallithea.config import conf path = os.path.join(root_path, 'rcextensions', '__init__.py') if os.path.isfile(path): rcext = create_module('rc', path) - EXT = rhodecode.EXTENSIONS = rcext + EXT = kallithea.EXTENSIONS = rcext log.debug('Found rcextensions now loading %s...' % rcext) # Additional mappings that are not present in the pygments lexers @@ -570,10 +604,10 @@ def load_rcextensions(root_path): # auto check if the module is not missing any data, set to default if is # this will help autoupdate new feature of rcext module - from rhodecode.config import rcextensions - for k in dir(rcextensions): - if not k.startswith('_') and not hasattr(EXT, k): - setattr(EXT, k, getattr(rcextensions, k)) + #from kallithea.config import rcextensions + #for k in dir(rcextensions): + # if not k.startswith('_') and not hasattr(EXT, k): + # setattr(EXT, k, getattr(rcextensions, k)) def get_custom_lexer(extension): @@ -581,11 +615,11 @@ def get_custom_lexer(extension): returns a custom lexer if it's defined in rcextensions module, or None if there's no custom lexer defined """ - import rhodecode + import kallithea from pygments import lexers #check if we didn't define this extension as other lexer - if rhodecode.EXTENSIONS and extension in rhodecode.EXTENSIONS.EXTRA_LEXERS: - _lexer_name = rhodecode.EXTENSIONS.EXTRA_LEXERS[extension] + if kallithea.EXTENSIONS and extension in kallithea.EXTENSIONS.EXTRA_LEXERS: + _lexer_name = kallithea.EXTENSIONS.EXTRA_LEXERS[extension] return lexers.get_lexer_by_name(_lexer_name) @@ -600,8 +634,8 @@ def create_test_index(repo_location, con :param full_index: """ - from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon - from rhodecode.lib.pidlock import DaemonLock, LockHeld + from kallithea.lib.indexers.daemon import WhooshIndexingDaemon + from kallithea.lib.pidlock import DaemonLock, LockHeld repo_location = repo_location @@ -624,8 +658,8 @@ def create_test_env(repos_test_path, con Makes a fresh database and install test repository into tmp dir """ - from rhodecode.lib.db_manage import DbManage - from rhodecode.tests import HG_REPO, GIT_REPO, TESTS_TMP_PATH + from kallithea.lib.db_manage import DbManage + from kallithea.tests import HG_REPO, GIT_REPO, TESTS_TMP_PATH # PART ONE create db dbconf = config['sqlalchemy.db1.url'] @@ -639,6 +673,7 @@ def create_test_env(repos_test_path, con dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=config['here'], tests=True) dbmanage.create_tables(override=True) + # for tests dynamically set new root paths based on generated content dbmanage.create_settings(dbmanage.config_prompt(repos_test_path)) dbmanage.create_default_user() dbmanage.admin_prompt() @@ -672,7 +707,7 @@ def create_test_env(repos_test_path, con tar.close() #LOAD VCS test stuff - from rhodecode.tests.vcs import setup_package + from kallithea.tests.vcs import setup_package setup_package() @@ -748,8 +783,8 @@ class BasePasterCommand(Command): """ logging.config.fileConfig(self.path_to_ini_file) from pylons import config - from rhodecode.model import init_model - from rhodecode.lib.utils2 import engine_from_config + from kallithea.model import init_model + from kallithea.lib.utils2 import engine_from_config #get to remove repos !! add_cache(config) @@ -760,11 +795,11 @@ class BasePasterCommand(Command): def check_git_version(): """ Checks what version of git is installed in system, and issues a warning - if it's too old for RhodeCode to properly work. + if it's too old for Kallithea to properly work. """ - from rhodecode import BACKENDS - from rhodecode.lib.vcs.backends.git.repository import GitRepository - from rhodecode.lib.vcs.conf import settings + from kallithea import BACKENDS + from kallithea.lib.vcs.backends.git.repository import GitRepository + from kallithea.lib.vcs.conf import settings from distutils.version import StrictVersion stdout, stderr = GitRepository._run_git_command('--version', _bare=True, @@ -791,7 +826,7 @@ def check_git_version(): if stderr: log.warning('Unable to detect git version, org error was: %r' % stderr) elif to_old_git: - log.warning('RhodeCode detected git version %s, which is too old ' + log.warning('Kallithea detected git version %s, which is too old ' 'for the system to function properly. Make sure ' 'its version is at least %s' % (ver, req_ver)) return _ver @@ -807,7 +842,7 @@ def jsonify(func, *args, **kwargs): """ from pylons.decorators.util import get_pylons - from rhodecode.lib.compat import json + from kallithea.lib.compat import json pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json; charset=utf-8' data = func(*args, **kwargs) @@ -819,3 +854,30 @@ def jsonify(func, *args, **kwargs): log.warning(msg) log.debug("Returning JSON wrapped action output") return json.dumps(data, encoding='utf-8') + + +def conditional_cache(region, prefix, condition, func): + """ + + Conditional caching function use like:: + def _c(arg): + #heavy computation function + return data + + # denpending from condition the compute is wrapped in cache or not + compute = conditional_cache('short_term', 'cache_desc', codnition=True, func=func) + return compute(arg) + + :param region: name of cache region + :param prefix: cache region prefix + :param condition: condition for cache to be triggered, and return data cached + :param func: wrapped heavy function to compute + + """ + wrapped = func + if condition: + log.debug('conditional_cache: True, wrapping call of ' + 'func: %s into %s region cache' % (region, func)) + wrapped = _cache_decorate((prefix,), None, None, region)(func) + + return wrapped diff --git a/rhodecode/lib/utils2.py b/kallithea/lib/utils2.py rename from rhodecode/lib/utils2.py rename to kallithea/lib/utils2.py --- a/rhodecode/lib/utils2.py +++ b/kallithea/lib/utils2.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.lib.utils - ~~~~~~~~~~~~~~~~~~~ - - Some simple helper functions - - :created_on: Jan 5, 2011 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.lib.utils +~~~~~~~~~~~~~~~~~~~ + +Some simple helper functions + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jan 5, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import os import re @@ -31,10 +34,12 @@ import uuid import datetime import traceback import webob +import urllib +import urlobject from pylons.i18n.translation import _, ungettext -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.compat import json +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.compat import json def __get_lem(): @@ -208,8 +213,8 @@ def safe_unicode(str_, from_encoding=Non return str_ if not from_encoding: - import rhodecode - DEFAULT_ENCODINGS = aslist(rhodecode.CONFIG.get('default_encoding', + import kallithea + DEFAULT_ENCODINGS = aslist(kallithea.CONFIG.get('default_encoding', 'utf8'), sep=',') from_encoding = DEFAULT_ENCODINGS @@ -257,8 +262,8 @@ def safe_str(unicode_, to_encoding=None) return unicode_ if not to_encoding: - import rhodecode - DEFAULT_ENCODINGS = aslist(rhodecode.CONFIG.get('default_encoding', + import kallithea + DEFAULT_ENCODINGS = aslist(kallithea.CONFIG.get('default_encoding', 'utf8'), sep=',') to_encoding = DEFAULT_ENCODINGS @@ -488,6 +493,30 @@ def credentials_filter(uri): return ''.join(uri) +def get_clone_url(uri_tmpl, qualifed_home_url, repo_name, repo_id, **override): + parsed_url = urlobject.URLObject(qualifed_home_url) + decoded_path = safe_unicode(urllib.unquote(parsed_url.path.rstrip('/'))) + args = { + 'scheme': parsed_url.scheme, + 'user': '', + 'netloc': parsed_url.netloc+decoded_path, # path if we use proxy-prefix + 'prefix': decoded_path, + 'repo': repo_name, + 'repoid': str(repo_id) + } + args.update(override) + args['user'] = urllib.quote(safe_str(args['user'])) + + for k, v in args.items(): + uri_tmpl = uri_tmpl.replace('{%s}' % k, v) + + # remove leading @ sign if it's present. Case of empty user + url_obj = urlobject.URLObject(uri_tmpl) + url = url_obj.with_netloc(url_obj.netloc.lstrip('@')) + + return safe_unicode(url) + + def get_changeset_safe(repo, rev): """ Safe version of get_changeset if this changeset doesn't exists for a @@ -496,16 +525,16 @@ def get_changeset_safe(repo, rev): :param repo: :param rev: """ - from rhodecode.lib.vcs.backends.base import BaseRepository - from rhodecode.lib.vcs.exceptions import RepositoryError - from rhodecode.lib.vcs.backends.base import EmptyChangeset + from kallithea.lib.vcs.backends.base import BaseRepository + from kallithea.lib.vcs.exceptions import RepositoryError + from kallithea.lib.vcs.backends.base import EmptyChangeset if not isinstance(repo, BaseRepository): raise Exception('You must pass an Repository ' 'object as first argument got %s', type(repo)) try: cs = repo.get_changeset(rev) - except RepositoryError: + except (RepositoryError, LookupError): cs = EmptyChangeset(requested_revision=rev) return cs @@ -588,7 +617,7 @@ def _extract_extras(env=None): env = os.environ try: - rc_extras = json.loads(env['RC_SCM_DATA']) + rc_extras = json.loads(env['KALLITHEA_EXTRAS']) except Exception: print os.environ print >> sys.stderr, traceback.format_exc() @@ -605,7 +634,7 @@ def _extract_extras(env=None): def _set_extras(extras): - os.environ['RC_SCM_DATA'] = json.dumps(extras) + os.environ['KALLITHEA_EXTRAS'] = json.dumps(extras) def unique_id(hexlen=32): @@ -643,13 +672,82 @@ def suuid(url=None, truncate_to=22, alph unique_id = int(unique_id / alphabet_length) return "".join(output)[:truncate_to] -def get_current_rhodecode_user(): + +def get_current_authuser(): """ - Gets rhodecode user from threadlocal tmpl_context variable if it's + Gets kallithea user from threadlocal tmpl_context variable if it's defined, else returns None. """ from pylons import tmpl_context - if hasattr(tmpl_context, 'rhodecode_user'): - return tmpl_context.rhodecode_user + if hasattr(tmpl_context, 'authuser'): + return tmpl_context.authuser return None + + +class OptionalAttr(object): + """ + Special Optional Option that defines other attribute. Example:: + + def test(apiuser, userid=Optional(OAttr('apiuser')): + user = Optional.extract(userid) + # calls + + """ + + def __init__(self, attr_name): + self.attr_name = attr_name + + def __repr__(self): + return '' % self.attr_name + + def __call__(self): + return self + +#alias +OAttr = OptionalAttr + + +class Optional(object): + """ + Defines an optional parameter:: + + param = param.getval() if isinstance(param, Optional) else param + param = param() if isinstance(param, Optional) else param + + is equivalent of:: + + param = Optional.extract(param) + + """ + + def __init__(self, type_): + self.type_ = type_ + + def __repr__(self): + return '' % self.type_.__repr__() + + def __call__(self): + return self.getval() + + def getval(self): + """ + returns value from this Optional instance + """ + if isinstance(self.type_, OAttr): + # use params name + return self.type_.attr_name + return self.type_ + + @classmethod + def extract(cls, val): + """ + Extracts value from Optional() instance + + :param val: + :return: original value if it's not Optional instance else + value of instance + """ + if isinstance(val, cls): + return val.getval() + return val diff --git a/rhodecode/lib/vcs/__init__.py b/kallithea/lib/vcs/__init__.py rename from rhodecode/lib/vcs/__init__.py rename to kallithea/lib/vcs/__init__.py --- a/rhodecode/lib/vcs/__init__.py +++ b/kallithea/lib/vcs/__init__.py @@ -20,8 +20,8 @@ __all__ = [ ] import sys -from rhodecode.lib.vcs.backends import get_repo, get_backend -from rhodecode.lib.vcs.exceptions import VCSError, RepositoryError, ChangesetError +from kallithea.lib.vcs.backends import get_repo, get_backend +from kallithea.lib.vcs.exceptions import VCSError, RepositoryError, ChangesetError def get_version(): @@ -34,7 +34,7 @@ def get_version(): def main(argv=None): if argv is None: argv = sys.argv - from rhodecode.lib.vcs.cli import ExecutionManager + from kallithea.lib.vcs.cli import ExecutionManager manager = ExecutionManager(argv) manager.execute() return 0 diff --git a/rhodecode/lib/vcs/backends/__init__.py b/kallithea/lib/vcs/backends/__init__.py rename from rhodecode/lib/vcs/backends/__init__.py rename to kallithea/lib/vcs/backends/__init__.py --- a/rhodecode/lib/vcs/backends/__init__.py +++ b/kallithea/lib/vcs/backends/__init__.py @@ -10,11 +10,11 @@ """ import os from pprint import pformat -from rhodecode.lib.vcs.conf import settings -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.utils.paths import abspath -from rhodecode.lib.vcs.utils.imports import import_class +from kallithea.lib.vcs.conf import settings +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.utils.paths import abspath +from kallithea.lib.vcs.utils.imports import import_class def get_repo(path=None, alias=None, create=False): diff --git a/rhodecode/lib/vcs/backends/base.py b/kallithea/lib/vcs/backends/base.py rename from rhodecode/lib/vcs/backends/base.py rename to kallithea/lib/vcs/backends/base.py --- a/rhodecode/lib/vcs/backends/base.py +++ b/kallithea/lib/vcs/backends/base.py @@ -12,12 +12,12 @@ import datetime import itertools -from rhodecode.lib.vcs.utils import author_name, author_email -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.utils.helpers import get_dict_for_attrs -from rhodecode.lib.vcs.conf import settings +from kallithea.lib.vcs.utils import author_name, author_email, safe_unicode +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.utils.helpers import get_dict_for_attrs +from kallithea.lib.vcs.conf import settings -from rhodecode.lib.vcs.exceptions import ( +from kallithea.lib.vcs.exceptions import ( ChangesetError, EmptyRepositoryError, NodeAlreadyAddedError, NodeAlreadyChangedError, NodeAlreadyExistsError, NodeAlreadyRemovedError, NodeDoesNotExistError, NodeNotChangedError, RepositoryError @@ -99,6 +99,10 @@ class BaseRepository(object): def name(self): raise NotImplementedError + @property + def name_unicode(self): + return safe_unicode(self.name) + @LazyProperty def owner(self): raise NotImplementedError @@ -133,6 +137,9 @@ class BaseRepository(object): """ raise NotImplementedError + def is_empty(self): + return self._empty + def get_last_change(self): self.get_changesets() @@ -905,6 +912,7 @@ class BaseInMemoryChangeset(object): try: old = p.get_node(node.path) missing.remove(node) + # if content actually changed, remove node from unchanged if old.content != node.content: not_changed.remove(node) except NodeDoesNotExistError: @@ -989,7 +997,7 @@ class EmptyChangeset(BaseChangeset): @LazyProperty def branch(self): - from rhodecode.lib.vcs.backends import get_backend + from kallithea.lib.vcs.backends import get_backend return get_backend(self.alias).DEFAULT_BRANCH_NAME @LazyProperty @@ -1027,4 +1035,4 @@ class CollectionGenerator(object): return CollectionGenerator(self.repo, sliced_revs) def __repr__(self): - return 'CollectionGenerator<%s>' % (len(self)) + return '' % (len(self)) diff --git a/rhodecode/lib/vcs/backends/git/__init__.py b/kallithea/lib/vcs/backends/git/__init__.py rename from rhodecode/lib/vcs/backends/git/__init__.py rename to kallithea/lib/vcs/backends/git/__init__.py diff --git a/rhodecode/lib/vcs/backends/git/changeset.py b/kallithea/lib/vcs/backends/git/changeset.py rename from rhodecode/lib/vcs/backends/git/changeset.py rename to kallithea/lib/vcs/backends/git/changeset.py --- a/rhodecode/lib/vcs/backends/git/changeset.py +++ b/kallithea/lib/vcs/backends/git/changeset.py @@ -3,20 +3,20 @@ from itertools import chain from dulwich import objects from subprocess import Popen, PIPE -from rhodecode.lib.vcs.conf import settings -from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyChangeset -from rhodecode.lib.vcs.exceptions import ( +from kallithea.lib.vcs.conf import settings +from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset +from kallithea.lib.vcs.exceptions import ( RepositoryError, ChangesetError, NodeDoesNotExistError, VCSError, ChangesetDoesNotExistError, ImproperArchiveTypeError ) -from rhodecode.lib.vcs.nodes import ( +from kallithea.lib.vcs.nodes import ( FileNode, DirNode, NodeKind, RootNode, RemovedFileNode, SubModuleNode, ChangedFileNodesGenerator, AddedFileNodesGenerator, RemovedFileNodesGenerator ) -from rhodecode.lib.vcs.utils import ( +from kallithea.lib.vcs.utils import ( safe_unicode, safe_str, safe_int, date_fromtimestamp ) -from rhodecode.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.utils.lazy import LazyProperty class GitChangeset(BaseChangeset): @@ -189,13 +189,15 @@ class GitChangeset(BaseChangeset): """ rev_filter = _git_path = settings.GIT_REV_FILTER so, se = self.repository.run_git_command( - "rev-list %s --children | grep '^%s'" % (rev_filter, self.raw_id) + "rev-list %s --children" % (rev_filter) ) children = [] + pat = re.compile(r'^%s' % self.raw_id) for l in so.splitlines(): - childs = l.split(' ')[1:] - children.extend(childs) + if pat.match(l): + childs = l.split(' ')[1:] + children.extend(childs) return [self.repository.get_changeset(cs) for cs in children] def next(self, branch=None): @@ -294,17 +296,15 @@ class GitChangeset(BaseChangeset): f_path = safe_str(path) if limit: - cmd = 'log -n %s --pretty="format: %%H" -s -p %s -- "%s"' % ( - safe_int(limit, 0), cs_id, f_path - ) + cmd = 'log -n %s --pretty="format: %%H" -s %s -- "%s"' % ( + safe_int(limit, 0), cs_id, f_path) else: - cmd = 'log --pretty="format: %%H" -s -p %s -- "%s"' % ( - cs_id, f_path - ) + cmd = 'log --pretty="format: %%H" -s %s -- "%s"' % ( + cs_id, f_path) so, se = self.repository.run_git_command(cmd) ids = re.findall(r'[0-9a-fA-F]{40}', so) - return [self.repository.get_changeset(id) for id in ids] + return [self.repository.get_changeset(sha) for sha in ids] def get_file_history_2(self, path): """ @@ -385,7 +385,7 @@ class GitChangeset(BaseChangeset): raise VCSError('You need to pass in a valid stream for filling' ' with archival data') popen = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True, - cwd=self.repository.path) + cwd=self.repository.path) buffer_size = 1024 * 8 chunk = popen.stdout.read(buffer_size) diff --git a/rhodecode/lib/vcs/backends/git/inmemory.py b/kallithea/lib/vcs/backends/git/inmemory.py rename from rhodecode/lib/vcs/backends/git/inmemory.py rename to kallithea/lib/vcs/backends/git/inmemory.py --- a/rhodecode/lib/vcs/backends/git/inmemory.py +++ b/kallithea/lib/vcs/backends/git/inmemory.py @@ -1,11 +1,12 @@ import time import datetime import posixpath +import stat from dulwich import objects from dulwich.repo import Repo -from rhodecode.lib.vcs.backends.base import BaseInMemoryChangeset -from rhodecode.lib.vcs.exceptions import RepositoryError -from rhodecode.lib.vcs.utils import safe_str +from kallithea.lib.vcs.backends.base import BaseInMemoryChangeset +from kallithea.lib.vcs.exceptions import RepositoryError +from kallithea.lib.vcs.utils import safe_str class GitInMemoryChangeset(BaseInMemoryChangeset): @@ -38,7 +39,6 @@ class GitInMemoryChangeset(BaseInMemoryC object_store = repo.object_store ENCODING = "UTF-8" - DIRMOD = 040000 # Create tree and populates it with blobs commit_tree = self.parents[0] and repo[self.parents[0]._commit.tree] or\ @@ -83,11 +83,11 @@ class GitInMemoryChangeset(BaseInMemoryC new_trees.append(curtree) for dirname in reversed_dirnames[:-1]: newtree = objects.Tree() - #newtree.add(DIRMOD, dirname, curtree.id) - newtree[dirname] = DIRMOD, curtree.id + #newtree.add(stat.S_IFDIR, dirname, curtree.id) + newtree[dirname] = stat.S_IFDIR, curtree.id new_trees.append(newtree) curtree = newtree - parent[reversed_dirnames[-1]] = DIRMOD, curtree.id + parent[reversed_dirnames[-1]] = stat.S_IFDIR, curtree.id else: parent.add(name=node_path, mode=node.mode, hexsha=blob.id) @@ -95,7 +95,7 @@ class GitInMemoryChangeset(BaseInMemoryC # Update ancestors for parent, tree, path in reversed([(a[1], b[1], b[0]) for a, b in zip(ancestors, ancestors[1:])]): - parent[path] = DIRMOD, tree.id + parent[path] = stat.S_IFDIR, tree.id object_store.add_object(tree) object_store.add_object(blob) @@ -192,8 +192,7 @@ class GitInMemoryChangeset(BaseInMemoryC tree = get_tree_for_dir(parent, dirname) if tree is None: tree = objects.Tree() - dirmode = 040000 - parent.add(dirmode, dirname, tree.id) + parent.add(stat.S_IFDIR, dirname, tree.id) parent = tree # Always append tree trees.append(tree) diff --git a/rhodecode/lib/vcs/backends/git/repository.py b/kallithea/lib/vcs/backends/git/repository.py rename from rhodecode/lib/vcs/backends/git/repository.py rename to kallithea/lib/vcs/backends/git/repository.py --- a/rhodecode/lib/vcs/backends/git/repository.py +++ b/kallithea/lib/vcs/backends/git/repository.py @@ -20,26 +20,26 @@ import string from dulwich.objects import Tag from dulwich.repo import Repo, NotGitRepository +from dulwich.config import ConfigFile -from rhodecode.lib.vcs import subprocessio -from rhodecode.lib.vcs.backends.base import BaseRepository, CollectionGenerator -from rhodecode.lib.vcs.conf import settings +from kallithea.lib.vcs import subprocessio +from kallithea.lib.vcs.backends.base import BaseRepository, CollectionGenerator +from kallithea.lib.vcs.conf import settings -from rhodecode.lib.vcs.exceptions import ( +from kallithea.lib.vcs.exceptions import ( BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError, TagDoesNotExistError ) -from rhodecode.lib.vcs.utils import safe_unicode, makedate, date_fromtimestamp -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.utils.ordered_dict import OrderedDict -from rhodecode.lib.vcs.utils.paths import abspath, get_user_home +from kallithea.lib.vcs.utils import safe_unicode, makedate, date_fromtimestamp +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.utils.ordered_dict import OrderedDict +from kallithea.lib.vcs.utils.paths import abspath, get_user_home -from rhodecode.lib.vcs.utils.hgcompat import ( +from kallithea.lib.vcs.utils.hgcompat import ( hg_url, httpbasicauthhandler, httpdigestauthhandler ) from .changeset import GitChangeset -from .config import ConfigFile from .inmemory import GitInMemoryChangeset from .workdir import GitWorkdir @@ -165,25 +165,31 @@ class GitRepository(BaseRepository): @classmethod def _check_url(cls, url): """ - Functon will check given url and try to verify if it's a valid - link. Sometimes it may happened that mercurial will issue basic + Function will check given url and try to verify if it's a valid + link. Sometimes it may happened that git will issue basic auth request that can cause whole API to hang when used from python or other external calls. - On failures it'll raise urllib2.HTTPError + On failures it'll raise urllib2.HTTPError, exception is also thrown + when the return code is non 200 """ # check first if it's not an local url if os.path.isdir(url) or url.startswith('file:'): return True - if('+' in url[:url.find('://')]): + if '+' in url[:url.find('://')]: url = url[url.find('+') + 1:] handlers = [] - test_uri, authinfo = hg_url(url).authinfo() + url_obj = hg_url(url) + test_uri, authinfo = url_obj.authinfo() + url_obj.passwd = '*****' + cleaned_uri = str(url_obj) + if not test_uri.endswith('info/refs'): test_uri = test_uri.rstrip('/') + '/info/refs' + if authinfo: #create a password manager passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() @@ -202,10 +208,19 @@ class GitRepository(BaseRepository): try: resp = o.open(req) - return resp.code == 200 + if resp.code != 200: + raise Exception('Return Code is not 200') except Exception, e: # means it cannot be cloned - raise urllib2.URLError("[%s] %s" % (url, e)) + raise urllib2.URLError("[%s] org_exc: %s" % (cleaned_uri, e)) + + # now detect if it's proper git repo + gitdata = resp.read() + if not 'service=git-upload-pack' in gitdata: + raise urllib2.URLError( + "url [%s] does not look like an git" % (cleaned_uri)) + + return True def _get_repo(self, create, src_url=None, update_after_clone=False, bare=False): @@ -220,7 +235,7 @@ class GitRepository(BaseRepository): self.clone(src_url, update_after_clone, bare) return Repo(self.path) elif create: - os.mkdir(self.path) + os.makedirs(self.path) if bare: return Repo.init_bare(self.path) else: @@ -274,8 +289,8 @@ class GitRepository(BaseRepository): try: revision = self.revisions[int(revision)] except Exception: - raise ChangesetDoesNotExistError("Revision %s does not exist " - "for this repository" % (revision)) + msg = ("Revision %s does not exist for %s" % (revision, self)) + raise ChangesetDoesNotExistError(msg) elif is_bstr: # get by branch/tag name @@ -289,8 +304,8 @@ class GitRepository(BaseRepository): return _tags_shas[_tags_shas.index(revision)] elif not SHA_PATTERN.match(revision) or revision not in self.revisions: - raise ChangesetDoesNotExistError("Revision %s does not exist " - "for this repository" % (revision)) + msg = ("Revision %s does not exist for %s" % (revision, self)) + raise ChangesetDoesNotExistError(msg) # Ensure we return full id if not SHA_PATTERN.match(str(revision)): @@ -348,13 +363,9 @@ class GitRepository(BaseRepository): @LazyProperty def description(self): - idx_loc = '' if self.bare else '.git' undefined_description = u'unknown' - description_path = os.path.join(self.path, idx_loc, 'description') - if os.path.isfile(description_path): - return safe_unicode(open(description_path).read()) - else: - return undefined_description + _desc = self._repo.get_description() + return safe_unicode(_desc or undefined_description) @LazyProperty def contact(self): @@ -631,7 +642,7 @@ class GitRepository(BaseRepository): *bare* git repository (no working directory at all). """ url = self._get_url(url) - cmd = ['clone'] + cmd = ['clone', '-q'] if bare: cmd.append('--bare') elif not update_after_clone: @@ -665,6 +676,13 @@ class GitRepository(BaseRepository): cmd = '''fetch %s -- %s''' % (url, refs) self.run_git_command(cmd) + def _update_server_info(self): + """ + runs gits update-server-info command in this repo instance + """ + from dulwich.server import update_server_info + update_server_info(self._repo) + @LazyProperty def workdir(self): """ diff --git a/rhodecode/lib/vcs/backends/git/workdir.py b/kallithea/lib/vcs/backends/git/workdir.py rename from rhodecode/lib/vcs/backends/git/workdir.py rename to kallithea/lib/vcs/backends/git/workdir.py --- a/rhodecode/lib/vcs/backends/git/workdir.py +++ b/kallithea/lib/vcs/backends/git/workdir.py @@ -1,7 +1,7 @@ import re -from rhodecode.lib.vcs.backends.base import BaseWorkdir -from rhodecode.lib.vcs.exceptions import RepositoryError -from rhodecode.lib.vcs.exceptions import BranchDoesNotExistError +from kallithea.lib.vcs.backends.base import BaseWorkdir +from kallithea.lib.vcs.exceptions import RepositoryError +from kallithea.lib.vcs.exceptions import BranchDoesNotExistError class GitWorkdir(BaseWorkdir): diff --git a/rhodecode/lib/vcs/backends/hg/__init__.py b/kallithea/lib/vcs/backends/hg/__init__.py rename from rhodecode/lib/vcs/backends/hg/__init__.py rename to kallithea/lib/vcs/backends/hg/__init__.py diff --git a/rhodecode/lib/vcs/backends/hg/changeset.py b/kallithea/lib/vcs/backends/hg/changeset.py rename from rhodecode/lib/vcs/backends/hg/changeset.py rename to kallithea/lib/vcs/backends/hg/changeset.py --- a/rhodecode/lib/vcs/backends/hg/changeset.py +++ b/kallithea/lib/vcs/backends/hg/changeset.py @@ -1,20 +1,20 @@ import os import posixpath -from rhodecode.lib.vcs.conf import settings -from rhodecode.lib.vcs.backends.base import BaseChangeset -from rhodecode.lib.vcs.exceptions import ( +from kallithea.lib.vcs.conf import settings +from kallithea.lib.vcs.backends.base import BaseChangeset +from kallithea.lib.vcs.exceptions import ( ChangesetDoesNotExistError, ChangesetError, ImproperArchiveTypeError, NodeDoesNotExistError, VCSError ) -from rhodecode.lib.vcs.nodes import ( +from kallithea.lib.vcs.nodes import ( AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode, NodeKind, RemovedFileNodesGenerator, RootNode, SubModuleNode ) -from rhodecode.lib.vcs.utils import safe_str, safe_unicode, date_fromtimestamp -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.utils.paths import get_dirs_for_path -from rhodecode.lib.vcs.utils.hgcompat import archival, hex +from kallithea.lib.vcs.utils import safe_str, safe_unicode, date_fromtimestamp +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.utils.paths import get_dirs_for_path +from kallithea.lib.vcs.utils.hgcompat import archival, hex class MercurialChangeset(BaseChangeset): diff --git a/rhodecode/lib/vcs/backends/hg/inmemory.py b/kallithea/lib/vcs/backends/hg/inmemory.py rename from rhodecode/lib/vcs/backends/hg/inmemory.py rename to kallithea/lib/vcs/backends/hg/inmemory.py --- a/rhodecode/lib/vcs/backends/hg/inmemory.py +++ b/kallithea/lib/vcs/backends/hg/inmemory.py @@ -1,10 +1,10 @@ import datetime import errno -from rhodecode.lib.vcs.backends.base import BaseInMemoryChangeset -from rhodecode.lib.vcs.exceptions import RepositoryError +from kallithea.lib.vcs.backends.base import BaseInMemoryChangeset +from kallithea.lib.vcs.exceptions import RepositoryError -from rhodecode.lib.vcs.utils.hgcompat import memfilectx, memctx, hex, tolocal +from kallithea.lib.vcs.utils.hgcompat import memfilectx, memctx, hex, tolocal class MercurialInMemoryChangeset(BaseInMemoryChangeset): diff --git a/rhodecode/lib/vcs/backends/hg/repository.py b/kallithea/lib/vcs/backends/hg/repository.py rename from rhodecode/lib/vcs/backends/hg/repository.py rename to kallithea/lib/vcs/backends/hg/repository.py --- a/rhodecode/lib/vcs/backends/hg/repository.py +++ b/kallithea/lib/vcs/backends/hg/repository.py @@ -17,23 +17,23 @@ import logging import datetime -from rhodecode.lib.vcs.backends.base import BaseRepository, CollectionGenerator -from rhodecode.lib.vcs.conf import settings +from kallithea.lib.vcs.backends.base import BaseRepository, CollectionGenerator +from kallithea.lib.vcs.conf import settings -from rhodecode.lib.vcs.exceptions import ( +from kallithea.lib.vcs.exceptions import ( BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, VCSError, TagAlreadyExistError, TagDoesNotExistError ) -from rhodecode.lib.vcs.utils import ( +from kallithea.lib.vcs.utils import ( author_email, author_name, date_fromtimestamp, makedate, safe_unicode ) -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.utils.ordered_dict import OrderedDict -from rhodecode.lib.vcs.utils.paths import abspath -from rhodecode.lib.vcs.utils.hgcompat import ( +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.utils.ordered_dict import OrderedDict +from kallithea.lib.vcs.utils.paths import abspath +from kallithea.lib.vcs.utils.hgcompat import ( ui, nullid, match, patch, diffopts, clone, get_contact, pull, localrepository, RepoLookupError, Abort, RepoError, hex, scmutil, hg_url, - httpbasicauthhandler, httpdigestauthhandler, peer + httpbasicauthhandler, httpdigestauthhandler, peer, httppeer ) from .changeset import MercurialChangeset @@ -288,26 +288,28 @@ class MercurialRepository(BaseRepository context=context))) @classmethod - def _check_url(cls, url): + def _check_url(cls, url, repoui=None): """ Function will check given url and try to verify if it's a valid link. Sometimes it may happened that mercurial will issue basic auth request that can cause whole API to hang when used from python or other external calls. - On failures it'll raise urllib2.HTTPError, return code 200 if url - is valid or True if it's a local path + On failures it'll raise urllib2.HTTPError, exception is also thrown + when the return code is non 200 """ - # check first if it's not an local url if os.path.isdir(url) or url.startswith('file:'): return True - if('+' in url[:url.find('://')]): + if '+' in url[:url.find('://')]: url = url[url.find('+') + 1:] handlers = [] - test_uri, authinfo = hg_url(url).authinfo() + url_obj = hg_url(url) + test_uri, authinfo = url_obj.authinfo() + url_obj.passwd = '*****' + cleaned_uri = str(url_obj) if authinfo: #create a password manager @@ -329,10 +331,21 @@ class MercurialRepository(BaseRepository try: resp = o.open(req) - return resp.code == 200 + if resp.code != 200: + raise Exception('Return Code is not 200') except Exception, e: # means it cannot be cloned - raise urllib2.URLError("[%s] %s" % (url, e)) + raise urllib2.URLError("[%s] org_exc: %s" % (cleaned_uri, e)) + + # now check if it's a proper hg repo + try: + repo_id = httppeer(repoui or ui.ui(), url).lookup('tip') + except Exception, e: + raise urllib2.URLError( + "url [%s] does not look like an hg repo org_exc: %s" + % (cleaned_uri, e)) + + return True def _get_repo(self, create, src_url=None, update_after_clone=False): """ @@ -352,7 +365,7 @@ class MercurialRepository(BaseRepository if not update_after_clone: opts.update({'noupdate': True}) try: - MercurialRepository._check_url(url) + MercurialRepository._check_url(url, self.baseui) clone(self.baseui, url, self.path, **opts) # except urllib2.URLError: # raise Abort("Got HTTP 404 error") @@ -378,8 +391,8 @@ class MercurialRepository(BaseRepository @LazyProperty def description(self): undefined_description = u'unknown' - return safe_unicode(self._repo.ui.config('web', 'description', - undefined_description, untrusted=True)) + _desc = self._repo.ui.config('web', 'description', None, untrusted=True) + return safe_unicode(_desc or undefined_description) @LazyProperty def contact(self): @@ -425,10 +438,13 @@ class MercurialRepository(BaseRepository try: revision = hex(self._repo.lookup(revision)) + except (LookupError, ): + msg = ("Ambiguous identifier `%s` for %s" % (revision, self)) + raise ChangesetDoesNotExistError(msg) except (IndexError, ValueError, RepoLookupError, TypeError): - raise ChangesetDoesNotExistError("Revision %s does not " - "exist for this repository" - % (revision)) + msg = ("Revision %s does not exist for %s" % (revision, self)) + raise ChangesetDoesNotExistError(msg) + return revision def _get_archives(self, archive_name='tip'): @@ -490,8 +506,8 @@ class MercurialRepository(BaseRepository "after end revision '%s'" % (start, end)) if branch_name and branch_name not in self.allbranches.keys(): - raise BranchDoesNotExistError('Branch %s not found in' - ' this repository' % branch_name) + msg = ("Branch %s not found in %s" % (branch_name, self)) + raise BranchDoesNotExistError(msg) if end_pos is not None: end_pos += 1 #filter branches diff --git a/rhodecode/lib/vcs/backends/hg/workdir.py b/kallithea/lib/vcs/backends/hg/workdir.py rename from rhodecode/lib/vcs/backends/hg/workdir.py rename to kallithea/lib/vcs/backends/hg/workdir.py --- a/rhodecode/lib/vcs/backends/hg/workdir.py +++ b/kallithea/lib/vcs/backends/hg/workdir.py @@ -1,7 +1,7 @@ -from rhodecode.lib.vcs.backends.base import BaseWorkdir -from rhodecode.lib.vcs.exceptions import BranchDoesNotExistError +from kallithea.lib.vcs.backends.base import BaseWorkdir +from kallithea.lib.vcs.exceptions import BranchDoesNotExistError -from rhodecode.lib.vcs.utils.hgcompat import hg_merge +from kallithea.lib.vcs.utils.hgcompat import hg_merge class MercurialWorkdir(BaseWorkdir): diff --git a/rhodecode/lib/vcs/conf/__init__.py b/kallithea/lib/vcs/conf/__init__.py rename from rhodecode/lib/vcs/conf/__init__.py rename to kallithea/lib/vcs/conf/__init__.py diff --git a/rhodecode/lib/vcs/conf/settings.py b/kallithea/lib/vcs/conf/settings.py rename from rhodecode/lib/vcs/conf/settings.py rename to kallithea/lib/vcs/conf/settings.py --- a/rhodecode/lib/vcs/conf/settings.py +++ b/kallithea/lib/vcs/conf/settings.py @@ -1,7 +1,7 @@ import os import tempfile -from rhodecode.lib.vcs.utils import aslist -from rhodecode.lib.vcs.utils.paths import get_user_home +from kallithea.lib.vcs.utils import aslist +from kallithea.lib.vcs.utils.paths import get_user_home abspath = lambda * p: os.path.abspath(os.path.join(*p)) @@ -25,8 +25,8 @@ GIT_EXECUTABLE_PATH = 'git' GIT_REV_FILTER = '--all' BACKENDS = { - 'hg': 'rhodecode.lib.vcs.backends.hg.MercurialRepository', - 'git': 'rhodecode.lib.vcs.backends.git.GitRepository', + 'hg': 'kallithea.lib.vcs.backends.hg.MercurialRepository', + 'git': 'kallithea.lib.vcs.backends.git.GitRepository', } ARCHIVE_SPECS = { diff --git a/rhodecode/lib/vcs/exceptions.py b/kallithea/lib/vcs/exceptions.py rename from rhodecode/lib/vcs/exceptions.py rename to kallithea/lib/vcs/exceptions.py diff --git a/rhodecode/lib/vcs/nodes.py b/kallithea/lib/vcs/nodes.py rename from rhodecode/lib/vcs/nodes.py rename to kallithea/lib/vcs/nodes.py --- a/rhodecode/lib/vcs/nodes.py +++ b/kallithea/lib/vcs/nodes.py @@ -13,10 +13,10 @@ import stat import posixpath import mimetypes -from rhodecode.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.vcs.exceptions import NodeError, RemovedFileNodeError -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.utils import safe_unicode, safe_str +from kallithea.lib.vcs.backends.base import EmptyChangeset +from kallithea.lib.vcs.exceptions import NodeError, RemovedFileNodeError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.utils import safe_unicode, safe_str class NodeKind: @@ -326,7 +326,7 @@ class FileNode(Node): return self._mimetype else: raise NodeError('given _mimetype attribute must be an 2 ' - 'element list or tuple') + 'element list or tuple') mtype, encoding = mimetypes.guess_type(self.name) @@ -337,6 +337,17 @@ class FileNode(Node): else: mtype = 'text/plain' encoding = None + + #try with pygments + try: + from pygments.lexers import get_lexer_for_filename + mt = get_lexer_for_filename(self.name).mimetypes + except Exception: + mt = None + + if mt: + mtype = mt[0] + return mtype, encoding @LazyProperty diff --git a/rhodecode/lib/vcs/subprocessio.py b/kallithea/lib/vcs/subprocessio.py rename from rhodecode/lib/vcs/subprocessio.py rename to kallithea/lib/vcs/subprocessio.py --- a/rhodecode/lib/vcs/subprocessio.py +++ b/kallithea/lib/vcs/subprocessio.py @@ -4,7 +4,7 @@ input, output, error streams into a mean stream processor exposing the output data as an iterator fitting to be a return value passed by a WSGI applicaiton to a WSGI server per PEP 3333. -Copyright (c) 2011 Daniel Dotsenko +Copyright (c) 2011 Daniel Dotsenko This file is part of git_http_backend.py Project. @@ -24,7 +24,7 @@ If not, see ccm: kr.clear() kr.wait(2) -# # this only works on 2.7.x and up -# if not kr.wait(10): -# raise Exception("Timed out while waiting for input to be read.") + # # this only works on 2.7.x and up + # if not kr.wait(10): + # raise Exception("Timed out while waiting for input to be read.") # instead we'll use this if len(t) > ccm + 3: - raise IOError("Timed out while waiting for input from subprocess.") + raise IOError( + "Timed out while waiting for input from subprocess.") t.append(b) da.set() b = s.read(cs) @@ -142,7 +144,7 @@ class InputStreamChunker(Thread): da.set() # for cases when done but there was no input. -class BufferedGenerator(): +class BufferedGenerator(object): """ Class behaves as a non-blocking, buffered pipe reader. Reads chunks of data (through a thread) @@ -164,7 +166,6 @@ class BufferedGenerator(): maxlen = None self.data = deque(starting_values, maxlen) - self.worker = InputStreamChunker(source, self.data, buffer_size, chunk_size) if starting_values: @@ -325,6 +326,7 @@ class SubprocessIOChunker(object): """ + def __init__(self, cmd, inputstream=None, buffer_size=65536, chunk_size=4096, starting_values=[], **kwargs): """ @@ -347,15 +349,14 @@ class SubprocessIOChunker(object): cmd = ' '.join(cmd) kwargs['shell'] = _shell - _p = subprocess.Popen(cmd, - bufsize=-1, - stdin=inputstream, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - **kwargs - ) + _p = subprocess.Popen(cmd, bufsize=-1, + stdin=inputstream, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + **kwargs) - bg_out = BufferedGenerator(_p.stdout, buffer_size, chunk_size, starting_values) + bg_out = BufferedGenerator(_p.stdout, buffer_size, chunk_size, + starting_values) bg_err = BufferedGenerator(_p.stderr, 16000, 1, bottomless=True) while not bg_out.done_reading and not bg_out.reading_paused and not bg_err.length: @@ -371,14 +372,16 @@ class SubprocessIOChunker(object): if _returncode or (_returncode is None and bg_err.length): try: _p.terminate() - except: + except Exception: pass bg_out.stop() bg_err.stop() err = '%s' % ''.join(bg_err) if err: - raise EnvironmentError("Subprocess exited due to an error:\n" + err) - raise EnvironmentError("Subprocess exited with non 0 ret code:%s" % _returncode) + raise EnvironmentError( + "Subprocess exited due to an error:\n" + err) + raise EnvironmentError( + "Subprocess exited with non 0 ret code:%s" % _returncode) self.process = _p self.output = bg_out diff --git a/rhodecode/lib/vcs/utils/__init__.py b/kallithea/lib/vcs/utils/__init__.py rename from rhodecode/lib/vcs/utils/__init__.py rename to kallithea/lib/vcs/utils/__init__.py --- a/rhodecode/lib/vcs/utils/__init__.py +++ b/kallithea/lib/vcs/utils/__init__.py @@ -80,7 +80,7 @@ def safe_unicode(str_, from_encoding=Non return str_ if not from_encoding: - from rhodecode.lib.vcs.conf import settings + from kallithea.lib.vcs.conf import settings from_encoding = settings.DEFAULT_ENCODINGS if not isinstance(from_encoding, (list, tuple)): @@ -127,7 +127,7 @@ def safe_str(unicode_, to_encoding=None) return unicode_ if not to_encoding: - from rhodecode.lib.vcs.conf import settings + from kallithea.lib.vcs.conf import settings to_encoding = settings.DEFAULT_ENCODINGS if not isinstance(to_encoding, (list, tuple)): diff --git a/rhodecode/lib/vcs/utils/annotate.py b/kallithea/lib/vcs/utils/annotate.py rename from rhodecode/lib/vcs/utils/annotate.py rename to kallithea/lib/vcs/utils/annotate.py --- a/rhodecode/lib/vcs/utils/annotate.py +++ b/kallithea/lib/vcs/utils/annotate.py @@ -3,8 +3,8 @@ import StringIO from pygments.formatters import HtmlFormatter from pygments import highlight -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.nodes import FileNode +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.nodes import FileNode def annotate_highlight(filenode, annotate_from_changeset_func=None, diff --git a/rhodecode/lib/vcs/utils/archivers.py b/kallithea/lib/vcs/utils/archivers.py rename from rhodecode/lib/vcs/utils/archivers.py rename to kallithea/lib/vcs/utils/archivers.py diff --git a/rhodecode/lib/vcs/utils/baseui_config.py b/kallithea/lib/vcs/utils/baseui_config.py rename from rhodecode/lib/vcs/utils/baseui_config.py rename to kallithea/lib/vcs/utils/baseui_config.py --- a/rhodecode/lib/vcs/utils/baseui_config.py +++ b/kallithea/lib/vcs/utils/baseui_config.py @@ -1,4 +1,4 @@ -from rhodecode.lib.vcs.utils.hgcompat import ui, config +from kallithea.lib.vcs.utils.hgcompat import ui, config def make_ui(self, path='hgwebdir.config'): diff --git a/rhodecode/lib/vcs/utils/compat.py b/kallithea/lib/vcs/utils/compat.py rename from rhodecode/lib/vcs/utils/compat.py rename to kallithea/lib/vcs/utils/compat.py diff --git a/rhodecode/lib/vcs/utils/diffs.py b/kallithea/lib/vcs/utils/diffs.py rename from rhodecode/lib/vcs/utils/diffs.py rename to kallithea/lib/vcs/utils/diffs.py --- a/rhodecode/lib/vcs/utils/diffs.py +++ b/kallithea/lib/vcs/utils/diffs.py @@ -9,9 +9,9 @@ import itertools from difflib import unified_diff -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.nodes import FileNode, NodeError -from rhodecode.lib.vcs.utils import safe_unicode +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.nodes import FileNode, NodeError +from kallithea.lib.vcs.utils import safe_unicode def get_udiff(filenode_old, filenode_new, show_whitespace=True): diff --git a/rhodecode/lib/vcs/utils/fakemod.py b/kallithea/lib/vcs/utils/fakemod.py rename from rhodecode/lib/vcs/utils/fakemod.py rename to kallithea/lib/vcs/utils/fakemod.py diff --git a/rhodecode/lib/vcs/utils/filesize.py b/kallithea/lib/vcs/utils/filesize.py rename from rhodecode/lib/vcs/utils/filesize.py rename to kallithea/lib/vcs/utils/filesize.py diff --git a/rhodecode/lib/vcs/utils/helpers.py b/kallithea/lib/vcs/utils/helpers.py rename from rhodecode/lib/vcs/utils/helpers.py rename to kallithea/lib/vcs/utils/helpers.py --- a/rhodecode/lib/vcs/utils/helpers.py +++ b/kallithea/lib/vcs/utils/helpers.py @@ -9,9 +9,9 @@ import time import datetime from subprocess import Popen, PIPE -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.exceptions import RepositoryError -from rhodecode.lib.vcs.utils.paths import abspath +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.exceptions import RepositoryError +from kallithea.lib.vcs.utils.paths import abspath ALIASES = ['hg', 'git'] @@ -67,7 +67,7 @@ def get_scms_for_path(path): :raises VCSError: if given ``path`` is not a directory """ - from rhodecode.lib.vcs.backends import get_backend + from kallithea.lib.vcs.backends import get_backend if hasattr(path, '__call__'): path = path() if not os.path.isdir(path): diff --git a/rhodecode/lib/vcs/utils/hgcompat.py b/kallithea/lib/vcs/utils/hgcompat.py rename from rhodecode/lib/vcs/utils/hgcompat.py rename to kallithea/lib/vcs/utils/hgcompat.py diff --git a/rhodecode/lib/vcs/utils/imports.py b/kallithea/lib/vcs/utils/imports.py rename from rhodecode/lib/vcs/utils/imports.py rename to kallithea/lib/vcs/utils/imports.py --- a/rhodecode/lib/vcs/utils/imports.py +++ b/kallithea/lib/vcs/utils/imports.py @@ -1,4 +1,4 @@ -from rhodecode.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.exceptions import VCSError def import_class(class_path): diff --git a/rhodecode/lib/vcs/utils/lazy.py b/kallithea/lib/vcs/utils/lazy.py rename from rhodecode/lib/vcs/utils/lazy.py rename to kallithea/lib/vcs/utils/lazy.py diff --git a/rhodecode/lib/vcs/utils/lockfiles.py b/kallithea/lib/vcs/utils/lockfiles.py rename from rhodecode/lib/vcs/utils/lockfiles.py rename to kallithea/lib/vcs/utils/lockfiles.py diff --git a/rhodecode/lib/vcs/utils/ordered_dict.py b/kallithea/lib/vcs/utils/ordered_dict.py rename from rhodecode/lib/vcs/utils/ordered_dict.py rename to kallithea/lib/vcs/utils/ordered_dict.py diff --git a/rhodecode/lib/vcs/utils/paths.py b/kallithea/lib/vcs/utils/paths.py rename from rhodecode/lib/vcs/utils/paths.py rename to kallithea/lib/vcs/utils/paths.py diff --git a/rhodecode/lib/vcs/utils/progressbar.py b/kallithea/lib/vcs/utils/progressbar.py rename from rhodecode/lib/vcs/utils/progressbar.py rename to kallithea/lib/vcs/utils/progressbar.py --- a/rhodecode/lib/vcs/utils/progressbar.py +++ b/kallithea/lib/vcs/utils/progressbar.py @@ -3,8 +3,8 @@ import sys import datetime import string -from rhodecode.lib.vcs.utils.filesize import filesizeformat -from rhodecode.lib.vcs.utils.helpers import get_total_seconds +from kallithea.lib.vcs.utils.filesize import filesizeformat +from kallithea.lib.vcs.utils.helpers import get_total_seconds class ProgressBarError(Exception): diff --git a/rhodecode/lib/vcs/utils/termcolors.py b/kallithea/lib/vcs/utils/termcolors.py rename from rhodecode/lib/vcs/utils/termcolors.py rename to kallithea/lib/vcs/utils/termcolors.py diff --git a/kallithea/lib/verlib.py b/kallithea/lib/verlib.py new file mode 100644 --- /dev/null +++ b/kallithea/lib/verlib.py @@ -0,0 +1,326 @@ +""" +"Rational" version definition and parsing for DistutilsVersionFight +discussion at PyCon 2009. +""" + +import sys +import re + +class IrrationalVersionError(Exception): + """This is an irrational version.""" + pass + +class HugeMajorVersionNumError(IrrationalVersionError): + """An irrational version because the major version number is huge + (often because a year or date was used). + + See `error_on_huge_major_num` option in `NormalizedVersion` for details. + This guard can be disabled by setting that option False. + """ + pass + +# A marker used in the second and third parts of the `parts` tuple, for +# versions that don't have those segments, to sort properly. An example +# of versions in sort order ('highest' last): +# 1.0b1 ((1,0), ('b',1), ('f',)) +# 1.0.dev345 ((1,0), ('f',), ('dev', 345)) +# 1.0 ((1,0), ('f',), ('f',)) +# 1.0.post256.dev345 ((1,0), ('f',), ('f', 'post', 256, 'dev', 345)) +# 1.0.post345 ((1,0), ('f',), ('f', 'post', 345, 'f')) +# ^ ^ ^ +# 'b' < 'f' ---------------------/ | | +# | | +# 'dev' < 'f' < 'post' -------------------/ | +# | +# 'dev' < 'f' ----------------------------------------------/ +# Other letters would do, but 'f' for 'final' is kind of nice. +FINAL_MARKER = ('f',) + +VERSION_RE = re.compile(r''' + ^ + (?P\d+\.\d+) # minimum 'N.N' + (?P(?:\.\d+)*) # any number of extra '.N' segments + (?: + (?P[abc]|rc) # 'a'=alpha, 'b'=beta, 'c'=release candidate + # 'rc'= alias for release candidate + (?P\d+(?:\.\d+)*) + )? + (?P(\.post(?P\d+))?(\.dev(?P\d+))?)? + $''', re.VERBOSE) + +class NormalizedVersion(object): + """A rational version. + + Good: + 1.2 # equivalent to "1.2.0" + 1.2.0 + 1.2a1 + 1.2.3a2 + 1.2.3b1 + 1.2.3c1 + 1.2.3.4 + TODO: fill this out + + Bad: + 1 # mininum two numbers + 1.2a # release level must have a release serial + 1.2.3b + """ + def __init__(self, s, error_on_huge_major_num=True): + """Create a NormalizedVersion instance from a version string. + + :param s {str} The version string. + :param error_on_huge_major_num {bool} Whether to consider an + apparent use of a year or full date as the major version number + an error. Default True. One of the observed patterns on PyPI before + the introduction of `NormalizedVersion` was version numbers like this: + 2009.01.03 + 20040603 + 2005.01 + This guard is here to strongly encourage the package author to + use an alternate version, because a release deployed into PyPI + and, e.g. downstream Linux package managers, will forever remove + the possibility of using a version number like "1.0" (i.e. + where the major number is less than that huge major number). + """ + self._parse(s, error_on_huge_major_num) + + @classmethod + def from_parts(cls, version, prerelease=FINAL_MARKER, + devpost=FINAL_MARKER): + return cls(cls.parts_to_str((version, prerelease, devpost))) + + def _parse(self, s, error_on_huge_major_num=True): + """Parses a string version into parts.""" + match = VERSION_RE.search(s) + if not match: + raise IrrationalVersionError(s) + + groups = match.groupdict() + parts = [] + + # main version + block = self._parse_numdots(groups['version'], s, False, 2) + extraversion = groups.get('extraversion') + if extraversion not in ('', None): + block += self._parse_numdots(extraversion[1:], s) + parts.append(tuple(block)) + + # prerelease + prerel = groups.get('prerel') + if prerel is not None: + block = [prerel] + block += self._parse_numdots(groups.get('prerelversion'), s, + pad_zeros_length=1) + parts.append(tuple(block)) + else: + parts.append(FINAL_MARKER) + + # postdev + if groups.get('postdev'): + post = groups.get('post') + dev = groups.get('dev') + postdev = [] + if post is not None: + postdev.extend([FINAL_MARKER[0], 'post', int(post)]) + if dev is None: + postdev.append(FINAL_MARKER[0]) + if dev is not None: + postdev.extend(['dev', int(dev)]) + parts.append(tuple(postdev)) + else: + parts.append(FINAL_MARKER) + self.parts = tuple(parts) + if error_on_huge_major_num and self.parts[0][0] > 1980: + raise HugeMajorVersionNumError("huge major version number, %r, " + "which might cause future problems: %r" % (self.parts[0][0], s)) + + def _parse_numdots(self, s, full_ver_str, drop_trailing_zeros=True, + pad_zeros_length=0): + """Parse 'N.N.N' sequences, return a list of ints. + + :param s {str} 'N.N.N..." sequence to be parsed + :param full_ver_str {str} The full version string from which this + comes. Used for error strings. + :param drop_trailing_zeros {bool} Whether to drop trailing zeros + from the returned list. Default True. + :param pad_zeros_length {int} The length to which to pad the + returned list with zeros, if necessary. Default 0. + """ + nums = [] + for n in s.split("."): + if len(n) > 1 and n[0] == '0': + raise IrrationalVersionError("cannot have leading zero in " + "version number segment: '%s' in %r" % (n, full_ver_str)) + nums.append(int(n)) + if drop_trailing_zeros: + while nums and nums[-1] == 0: + nums.pop() + while len(nums) < pad_zeros_length: + nums.append(0) + return nums + + def __str__(self): + return self.parts_to_str(self.parts) + + @classmethod + def parts_to_str(cls, parts): + """Transforms a version expressed in tuple into its string + representation.""" + # XXX This doesn't check for invalid tuples + main, prerel, postdev = parts + s = '.'.join(str(v) for v in main) + if prerel is not FINAL_MARKER: + s += prerel[0] + s += '.'.join(str(v) for v in prerel[1:]) + if postdev and postdev is not FINAL_MARKER: + if postdev[0] == 'f': + postdev = postdev[1:] + i = 0 + while i < len(postdev): + if i % 2 == 0: + s += '.' + s += str(postdev[i]) + i += 1 + return s + + def __repr__(self): + return "%s('%s')" % (self.__class__.__name__, self) + + def _cannot_compare(self, other): + raise TypeError("cannot compare %s and %s" + % (type(self).__name__, type(other).__name__)) + + def __eq__(self, other): + if not isinstance(other, NormalizedVersion): + self._cannot_compare(other) + return self.parts == other.parts + + def __lt__(self, other): + if not isinstance(other, NormalizedVersion): + self._cannot_compare(other) + return self.parts < other.parts + + def __ne__(self, other): + return not self.__eq__(other) + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__eq__(other) or self.__lt__(other) + + def __ge__(self, other): + return self.__eq__(other) or self.__gt__(other) + +def suggest_normalized_version(s): + """Suggest a normalized version close to the given version string. + + If you have a version string that isn't rational (i.e. NormalizedVersion + doesn't like it) then you might be able to get an equivalent (or close) + rational version from this function. + + This does a number of simple normalizations to the given string, based + on observation of versions currently in use on PyPI. Given a dump of + those version during PyCon 2009, 4287 of them: + - 2312 (53.93%) match NormalizedVersion without change + - with the automatic suggestion + - 3474 (81.04%) match when using this suggestion method + + :param s {str} An irrational version string. + :returns: A rational version string, or None, if couldn't determine one. + """ + try: + NormalizedVersion(s) + return s # already rational + except IrrationalVersionError: + pass + + rs = s.lower() + + # part of this could use maketrans + for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'), + ('beta', 'b'), ('rc', 'c'), ('-final', ''), + ('-pre', 'c'), + ('-release', ''), ('.release', ''), ('-stable', ''), + ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''), + ('final', '')): + rs = rs.replace(orig, repl) + + # if something ends with dev or pre, we add a 0 + rs = re.sub(r"pre$", r"pre0", rs) + rs = re.sub(r"dev$", r"dev0", rs) + + # if we have something like "b-2" or "a.2" at the end of the + # version, that is pobably beta, alpha, etc + # let's remove the dash or dot + rs = re.sub(r"([abc|rc])[\-\.](\d+)$", r"\1\2", rs) + + # 1.0-dev-r371 -> 1.0.dev371 + # 0.1-dev-r79 -> 0.1.dev79 + rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs) + + # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1 + rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs) + + # Clean: v0.3, v1.0 + if rs.startswith('v'): + rs = rs[1:] + + # Clean leading '0's on numbers. + #TODO: unintended side-effect on, e.g., "2003.05.09" + # PyPI stats: 77 (~2%) better + rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) + + # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers + # zero. + # PyPI stats: 245 (7.56%) better + rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs) + + # the 'dev-rNNN' tag is a dev tag + rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs) + + # clean the - when used as a pre delimiter + rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs) + + # a terminal "dev" or "devel" can be changed into ".dev0" + rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs) + + # a terminal "dev" can be changed into ".dev0" + rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs) + + # a terminal "final" or "stable" can be removed + rs = re.sub(r"(final|stable)$", "", rs) + + # The 'r' and the '-' tags are post release tags + # 0.4a1.r10 -> 0.4a1.post10 + # 0.9.33-17222 -> 0.9.3.post17222 + # 0.9.33-r17222 -> 0.9.3.post17222 + rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs) + + # Clean 'r' instead of 'dev' usage: + # 0.9.33+r17222 -> 0.9.3.dev17222 + # 1.0dev123 -> 1.0.dev123 + # 1.0.git123 -> 1.0.dev123 + # 1.0.bzr123 -> 1.0.dev123 + # 0.1a0dev.123 -> 0.1a0.dev123 + # PyPI stats: ~150 (~4%) better + rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs) + + # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage: + # 0.2.pre1 -> 0.2c1 + # 0.2-c1 -> 0.2c1 + # 1.0preview123 -> 1.0c123 + # PyPI stats: ~21 (0.62%) better + rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) + + + # Tcl/Tk uses "px" for their post release markers + rs = re.sub(r"p(\d+)$", r".post\1", rs) + + try: + NormalizedVersion(rs) + return rs # already rational + except IrrationalVersionError: + pass + return None diff --git a/rhodecode/model/__init__.py b/kallithea/model/__init__.py rename from rhodecode/model/__init__.py rename to kallithea/model/__init__.py --- a/rhodecode/model/__init__.py +++ b/kallithea/model/__init__.py @@ -1,33 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.__init__ - ~~~~~~~~~~~~~~~~~~~~~~~~ - - The application's model objects - - :created_on: Nov 25, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. - - - :example: - - .. code-block:: python - - from paste.deploy import appconfig - from pylons import config - from sqlalchemy import engine_from_config - from rhodecode.config.environment import load_environment - - conf = appconfig('config:development.ini', relative_to = './../../') - load_environment(conf.global_conf, conf.local_conf) - - engine = engine_from_config(config, 'sqlalchemy.') - init_model(engine) - # RUN YOUR CODE HERE - -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -40,10 +11,42 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.__init__ +~~~~~~~~~~~~~~~~~~~~~~~~ + +The application's model objects + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Nov 25, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + + +:example: + + .. code-block:: python + + from paste.deploy import appconfig + from pylons import config + from sqlalchemy import engine_from_config + from kallithea.config.environment import load_environment + + conf = appconfig('config:development.ini', relative_to = './../../') + load_environment(conf.global_conf, conf.local_conf) + + engine = engine_from_config(config, 'sqlalchemy.') + init_model(engine) + # RUN YOUR CODE HERE + +""" + import logging -from rhodecode.model import meta -from rhodecode.lib.utils2 import safe_str, obfuscate_url_pw +from kallithea.model import meta +from kallithea.lib.utils2 import safe_str, obfuscate_url_pw log = logging.getLogger(__name__) @@ -63,7 +66,7 @@ def init_model(engine): class BaseModel(object): """ - Base Model for all RhodeCode models, it adds sql alchemy session + Base Model for all Kallithea models, it adds sql alchemy session into instance of model :param sa: If passed it reuses this session instead of creating a new one @@ -106,7 +109,7 @@ class BaseModel(object): :param user: UserID, username, or User instance """ - from rhodecode.model.db import User + from kallithea.model.db import User return self._get_instance(User, user, callback=User.get_by_username) @@ -116,7 +119,7 @@ class BaseModel(object): :param repository: RepoID, repository name or Repository Instance """ - from rhodecode.model.db import Repository + from kallithea.model.db import Repository return self._get_instance(Repository, repository, callback=Repository.get_by_repo_name) @@ -126,12 +129,13 @@ class BaseModel(object): :param permission: PermissionID, permission_name or Permission instance """ - from rhodecode.model.db import Permission + from kallithea.model.db import Permission return self._get_instance(Permission, permission, callback=Permission.get_by_key) - def get_all(self): + @classmethod + def get_all(cls): """ Returns all instances of what is defined in `cls` class variable """ - return self.cls.getAll() + return cls.cls.getAll() diff --git a/kallithea/model/api_key.py b/kallithea/model/api_key.py new file mode 100644 --- /dev/null +++ b/kallithea/model/api_key.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.api_key +~~~~~~~~~~~~~~~~~~~~~~~ + +api key model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Sep 8, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + +from __future__ import with_statement +import time +import logging +import traceback +from sqlalchemy import or_ + +from kallithea.lib.utils2 import generate_api_key +from kallithea.model import BaseModel +from kallithea.model.db import UserApiKeys +from kallithea.model.meta import Session + +log = logging.getLogger(__name__) + + +class ApiKeyModel(BaseModel): + cls = UserApiKeys + + def create(self, user, description, lifetime=-1): + """ + :param user: user or user_id + :param description: description of ApiKey + :param lifetime: expiration time in seconds + """ + user = self._get_user(user) + + new_api_key = UserApiKeys() + new_api_key.api_key = generate_api_key(user.username) + new_api_key.user_id = user.user_id + new_api_key.description = description + new_api_key.expires = time.time() + (lifetime * 60) if lifetime != -1 else -1 + Session().add(new_api_key) + + return new_api_key + + def delete(self, api_key, user=None): + """ + Deletes given api_key, if user is set it also filters the object for + deletion by given user. + """ + api_key = UserApiKeys.query().filter(UserApiKeys.api_key == api_key) + + if user: + user = self._get_user(user) + api_key = api_key.filter(UserApiKeys.user_id == user.user_id) + + api_key = api_key.scalar() + try: + Session().delete(api_key) + except Exception: + log.error(traceback.format_exc()) + raise + + def get_api_keys(self, user, show_expired=True): + user = self._get_user(user) + user_api_keys = UserApiKeys.query()\ + .filter(UserApiKeys.user_id == user.user_id) + if not show_expired: + user_api_keys = user_api_keys\ + .filter(or_(UserApiKeys.expires == -1, + UserApiKeys.expires >= time.time())) + return user_api_keys diff --git a/rhodecode/model/changeset_status.py b/kallithea/model/changeset_status.py rename from rhodecode/model/changeset_status.py rename to kallithea/model/changeset_status.py --- a/rhodecode/model/changeset_status.py +++ b/kallithea/model/changeset_status.py @@ -1,13 +1,16 @@ # -*- coding: utf-8 -*- """ - rhodecode.model.changeset_status - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +kallithea.model.changeset_status +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Changeset status conttroller - :created_on: Apr 30, 2012 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 30, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. """ # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -26,9 +29,9 @@ import logging from collections import defaultdict -from rhodecode.model import BaseModel -from rhodecode.model.db import ChangesetStatus, PullRequest -from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError +from kallithea.model import BaseModel +from kallithea.model.db import ChangesetStatus, PullRequest +from kallithea.lib.exceptions import StatusChangeOnClosedPullRequestError log = logging.getLogger(__name__) @@ -130,7 +133,7 @@ class ChangesetStatusModel(BaseModel): q = ChangesetStatus.query() if not comment: - from rhodecode.model.comment import ChangesetCommentsModel + from kallithea.model.comment import ChangesetCommentsModel comment = ChangesetCommentsModel().create( text=u'Auto status change to %s' % (ChangesetStatus.get_status_lbl(status)), repo=repo, diff --git a/rhodecode/model/comment.py b/kallithea/model/comment.py rename from rhodecode/model/comment.py rename to kallithea/model/comment.py --- a/rhodecode/model/comment.py +++ b/kallithea/model/comment.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.comment - ~~~~~~~~~~~~~~~~~~~~~~~ - - comments model for RhodeCode - - :created_on: Nov 11, 2011 - :author: marcink - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.comment +~~~~~~~~~~~~~~~~~~~~~~~ + +comments model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Nov 11, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import logging import traceback @@ -29,13 +31,13 @@ import traceback from pylons.i18n.translation import _ from sqlalchemy.util.compat import defaultdict -from rhodecode.lib.utils2 import extract_mentioned_users, safe_unicode -from rhodecode.lib import helpers as h -from rhodecode.model import BaseModel -from rhodecode.model.db import ChangesetComment, User, Repository, \ +from kallithea.lib.utils2 import extract_mentioned_users, safe_unicode +from kallithea.lib import helpers as h +from kallithea.model import BaseModel +from kallithea.model.db import ChangesetComment, User, Repository, \ Notification, PullRequest -from rhodecode.model.notification import NotificationModel -from rhodecode.model.meta import Session +from kallithea.model.notification import NotificationModel +from kallithea.model.meta import Session log = logging.getLogger(__name__) @@ -95,7 +97,7 @@ class ChangesetCommentsModel(BaseModel): (user.username, h.short_id(revision)) # get the current participants of this changeset recipients = ChangesetComment.get_users(revision=revision) - # add changeset author if it's in rhodecode system + # add changeset author if it's in kallithea system cs_author = User.get_from_cs_author(cs.author) if not cs_author: #use repo owner if we cannot extract the author correctly diff --git a/rhodecode/model/db.py b/kallithea/model/db.py rename from rhodecode/model/db.py rename to kallithea/model/db.py --- a/rhodecode/model/db.py +++ b/kallithea/model/db.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.db - ~~~~~~~~~~~~~~~~~~ - - Database Models for RhodeCode - - :created_on: Apr 08, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.db +~~~~~~~~~~~~~~~~~~ + +Database Models for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 08, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import os import time @@ -30,6 +32,7 @@ import datetime import traceback import hashlib import collections +import functools from sqlalchemy import * from sqlalchemy.ext.hybrid import hybrid_property @@ -40,18 +43,20 @@ from webob.exc import HTTPNotFound from pylons.i18n.translation import lazy_ugettext as _ -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.utils.helpers import get_scm -from rhodecode.lib.vcs.exceptions import VCSError -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.backends.base import EmptyChangeset - -from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ - safe_unicode, remove_suffix, remove_prefix, time_to_datetime, _set_extras -from rhodecode.lib.compat import json -from rhodecode.lib.caching_query import FromCache - -from rhodecode.model.meta import Base, Session +from kallithea import DB_PREFIX +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.utils.helpers import get_scm +from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.backends.base import EmptyChangeset + +from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ + safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int, \ + get_clone_url +from kallithea.lib.compat import json +from kallithea.lib.caching_query import FromCache + +from kallithea.model.meta import Base, Session URL_SEP = '/' log = logging.getLogger(__name__) @@ -146,24 +151,40 @@ class BaseModel(object): def __repr__(self): if hasattr(self, '__unicode__'): # python repr needs to return str - return safe_str(self.__unicode__()) + try: + return safe_str(self.__unicode__()) + except UnicodeDecodeError: + pass return '' % (self.__class__.__name__) -class RhodeCodeSetting(Base, BaseModel): - __tablename__ = 'rhodecode_settings' +class Setting(Base, BaseModel): + __tablename__ = DB_PREFIX + 'settings' + __table_args__ = ( UniqueConstraint('app_settings_name'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) + + SETTINGS_TYPES = { + 'str': safe_str, + 'int': safe_int, + 'unicode': safe_unicode, + 'bool': str2bool, + 'list': functools.partial(aslist, sep=',') + } + DEFAULT_UPDATE_URL = '' + app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) - app_settings_name = Column("app_settings_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - _app_settings_value = Column("app_settings_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - - def __init__(self, k='', v=''): - self.app_settings_name = k - self.app_settings_value = v + app_settings_name = Column("app_settings_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + _app_settings_value = Column("app_settings_value", String(4096, convert_unicode=False), nullable=True, unique=None, default=None) + _app_settings_type = Column("app_settings_type", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + + def __init__(self, key='', val='', type='unicode'): + self.app_settings_name = key + self.app_settings_value = val + self.app_settings_type = type @validates('_app_settings_value') def validate_settings_value(self, key, val): @@ -173,13 +194,9 @@ class RhodeCodeSetting(Base, BaseModel): @hybrid_property def app_settings_value(self): v = self._app_settings_value - if self.app_settings_name in ["ldap_active", - "default_repo_enable_statistics", - "default_repo_enable_locking", - "default_repo_private", - "default_repo_enable_downloads"]: - v = str2bool(v) - return v + _type = self.app_settings_type + converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode'] + return converter(v) @app_settings_value.setter def app_settings_value(self, val): @@ -190,10 +207,21 @@ class RhodeCodeSetting(Base, BaseModel): """ self._app_settings_value = safe_unicode(val) + @hybrid_property + def app_settings_type(self): + return self._app_settings_type + + @app_settings_type.setter + def app_settings_type(self, val): + if val not in self.SETTINGS_TYPES: + raise Exception('type must be one of %s got %s' + % (self.SETTINGS_TYPES.keys(), val)) + self._app_settings_type = val + def __unicode__(self): - return u"<%s('%s:%s')>" % ( + return u"<%s('%s:%s[%s]')>" % ( self.__class__.__name__, - self.app_settings_name, self.app_settings_value + self.app_settings_name, self.app_settings_value, self.app_settings_type ) @classmethod @@ -202,10 +230,36 @@ class RhodeCodeSetting(Base, BaseModel): .filter(cls.app_settings_name == key).scalar() @classmethod - def get_by_name_or_create(cls, key): + def get_by_name_or_create(cls, key, val='', type='unicode'): res = cls.get_by_name(key) if not res: - res = cls(key) + res = cls(key, val, type) + return res + + @classmethod + def create_or_update(cls, key, val=Optional(''), type=Optional('unicode')): + """ + Creates or updates Kallithea setting. If updates is triggered it will only + update parameters that are explicityl set Optional instance will be skipped + + :param key: + :param val: + :param type: + :return: + """ + res = cls.get_by_name(key) + if not res: + val = Optional.extract(val) + type = Optional.extract(type) + res = cls(key, val, type) + else: + res.app_settings_name = key + if not isinstance(val, Optional): + # update if set + res.app_settings_value = val + if not isinstance(type, Optional): + # update if set + res.app_settings_type = type return res @classmethod @@ -220,15 +274,20 @@ class RhodeCodeSetting(Base, BaseModel): raise Exception('Could not get application settings !') settings = {} for each in ret: - settings['rhodecode_' + each.app_settings_name] = \ + settings[each.app_settings_name] = \ each.app_settings_value return settings @classmethod - def get_ldap_settings(cls, cache=False): + def get_auth_plugins(cls, cache=False): + auth_plugins = cls.get_by_name("auth_plugins").app_settings_value + return auth_plugins + + @classmethod + def get_auth_settings(cls, cache=False): ret = cls.query()\ - .filter(cls.app_settings_name.startswith('ldap_')).all() + .filter(cls.app_settings_name.startswith('auth_')).all() fd = {} for row in ret: fd.update({row.app_settings_name: row.app_settings_value}) @@ -248,13 +307,30 @@ class RhodeCodeSetting(Base, BaseModel): return fd - -class RhodeCodeUi(Base, BaseModel): - __tablename__ = 'rhodecode_ui' + @classmethod + def get_server_info(cls): + import pkg_resources + import platform + import kallithea + from kallithea.lib.utils import check_git_version + mods = [(p.project_name, p.version) for p in pkg_resources.working_set] + info = { + 'modules': sorted(mods, key=lambda k: k[0].lower()), + 'py_version': platform.python_version(), + 'platform': safe_unicode(platform.platform()), + 'kallithea_version': kallithea.__version__, + 'git_version': safe_unicode(check_git_version()), + 'git_path': kallithea.CONFIG.get('git_path') + } + return info + + +class Ui(Base, BaseModel): + __tablename__ = DB_PREFIX + 'ui' __table_args__ = ( UniqueConstraint('ui_key'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) HOOK_UPDATE = 'changegroup.update' @@ -265,9 +341,9 @@ class RhodeCodeUi(Base, BaseModel): HOOK_PRE_PULL = 'preoutgoing.pre_pull' ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) - ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + ui_section = Column("ui_section", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_key = Column("ui_key", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_value = Column("ui_value", String(255, convert_unicode=False), nullable=True, unique=None, default=None) ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) # def __init__(self, section='', key='', value=''): @@ -311,8 +387,8 @@ class RhodeCodeUi(Base, BaseModel): Session().add(new_ui) def __repr__(self): - return '' % (self.__class__.__name__, self.ui_key, - self.ui_value) + return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section, + self.ui_key, self.ui_value) class User(Base, BaseModel): @@ -322,22 +398,26 @@ class User(Base, BaseModel): Index('u_username_idx', 'username'), Index('u_email_idx', 'email'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) DEFAULT_USER = 'default' + DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}' user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) - username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + username = Column("username", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + password = Column("password", String(255, convert_unicode=False), nullable=True, unique=None, default=None) active = Column("active", Boolean(), nullable=True, unique=None, default=True) admin = Column("admin", Boolean(), nullable=True, unique=None, default=False) - name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + name = Column("firstname", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + lastname = Column("lastname", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + _email = Column("email", String(255, convert_unicode=False), nullable=True, unique=None, default=None) last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) - ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + extern_type = Column("extern_type", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + extern_name = Column("extern_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False), nullable=True, unique=None, default=None) inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + _user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data user_log = relationship('UserLog') user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') @@ -358,6 +438,9 @@ class User(Base, BaseModel): user_comments = relationship('ChangesetComment', cascade='all') #extra emails for this user user_emails = relationship('UserEmailMap', cascade='all') + #extra api keys + user_api_keys = relationship('UserApiKeys', cascade='all') + @hybrid_property def email(self): @@ -378,6 +461,11 @@ class User(Base, BaseModel): return [self.email] + [x.email for x in other] @property + def api_keys(self): + other = UserApiKeys.query().filter(UserApiKeys.user==self).all() + return [self.api_key] + [x.api_key for x in other] + + @property def ip_addresses(self): ret = UserIpMap.query().filter(UserIpMap.user == self).all() return [x.ip_addr for x in ret] @@ -412,13 +500,30 @@ class User(Base, BaseModel): """ Returns instance of AuthUser for this user """ - from rhodecode.lib.auth import AuthUser + from kallithea.lib.auth import AuthUser return AuthUser(user_id=self.user_id, api_key=self.api_key, username=self.username) + @hybrid_property + def user_data(self): + if not self._user_data: + return {} + + try: + return json.loads(self._user_data) + except TypeError: + return {} + + @user_data.setter + def user_data(self, val): + try: + self._user_data = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + def __unicode__(self): return u"<%s('id:%s:%s')>" % (self.__class__.__name__, - self.user_id, self.username) + self.user_id, self.username) @classmethod def get_by_username(cls, username, case_insensitive=False, cache=False): @@ -436,13 +541,24 @@ class User(Base, BaseModel): return q.scalar() @classmethod - def get_by_api_key(cls, api_key, cache=False): + def get_by_api_key(cls, api_key, cache=False, fallback=True): q = cls.query().filter(cls.api_key == api_key) if cache: q = q.options(FromCache("sql_cache_short", "get_api_key_%s" % api_key)) - return q.scalar() + res = q.scalar() + + if fallback and not res: + #fallback to additional keys + _res = UserApiKeys.query()\ + .filter(UserApiKeys.api_key == api_key)\ + .filter(or_(UserApiKeys.expires == -1, + UserApiKeys.expires >= time.time()))\ + .first() + if _res: + res = _res.user + return res @classmethod def get_by_email(cls, email, case_insensitive=False, cache=False): @@ -478,7 +594,7 @@ class User(Base, BaseModel): :param author: """ - from rhodecode.lib.helpers import email, author_name + from kallithea.lib.helpers import email, author_name # Valid email in the attribute passed, see if they're in the system _email = email(author) if _email: @@ -524,9 +640,11 @@ class User(Base, BaseModel): email=user.email, emails=user.emails, api_key=user.api_key, + api_keys=user.api_keys, active=user.active, admin=user.admin, - ldap_dn=user.ldap_dn, + extern_type=user.extern_type, + extern_name=user.extern_name, last_login=user.last_login, ip_addresses=user.ip_addresses ) @@ -543,19 +661,46 @@ class User(Base, BaseModel): return data +class UserApiKeys(Base, BaseModel): + __tablename__ = 'user_api_keys' + __table_args__ = ( + Index('uak_api_key_idx', 'api_key'), + Index('uak_api_key_expires_idx', 'api_key', 'expires'), + UniqueConstraint('api_key'), + {'extend_existing': True, 'mysql_engine': 'InnoDB', + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} + ) + __mapper_args__ = {} + + user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + api_key = Column("api_key", String(255, convert_unicode=False), nullable=False, unique=True) + description = Column('description', UnicodeText(1024)) + expires = Column('expires', Float(53), nullable=False) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + user = relationship('User', lazy='joined') + + @property + def expired(self): + if self.expires == -1: + return False + return time.time() > self.expires + + class UserEmailMap(Base, BaseModel): __tablename__ = 'user_email_map' __table_args__ = ( Index('uem_email_idx', 'email'), UniqueConstraint('email'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) __mapper_args__ = {} email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) - _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + _email = Column("email", String(255, convert_unicode=False), nullable=True, unique=False, default=None) user = relationship('User', lazy='joined') @validates('_email') @@ -580,19 +725,19 @@ class UserIpMap(Base, BaseModel): __table_args__ = ( UniqueConstraint('user_id', 'ip_addr'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) __mapper_args__ = {} ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) - ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + ip_addr = Column("ip_addr", String(255, convert_unicode=False), nullable=True, unique=False, default=None) active = Column("active", Boolean(), nullable=True, unique=None, default=True) user = relationship('User', lazy='joined') @classmethod def _get_ip_range(cls, ip_addr): - from rhodecode.lib import ipaddr + from kallithea.lib import ipaddr net = ipaddr.IPNetwork(address=ip_addr) return [str(net.network), str(net.broadcast)] @@ -602,20 +747,23 @@ class UserIpMap(Base, BaseModel): ip_range=self._get_ip_range(self.ip_addr) ) + def __unicode__(self): + return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__, + self.user_id, self.ip_addr) class UserLog(Base, BaseModel): __tablename__ = 'user_logs' __table_args__ = ( {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) - username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + username = Column("username", String(255, convert_unicode=False), nullable=True, unique=None, default=None) repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True) - repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + repository_name = Column("repository_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + user_ip = Column("user_ip", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + action = Column("action", UnicodeText(1200000, convert_unicode=False), nullable=True, unique=None, default=None) action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None) def __unicode__(self): @@ -635,14 +783,17 @@ class UserGroup(Base, BaseModel): __tablename__ = 'users_groups' __table_args__ = ( {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) - users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + users_group_name = Column("users_group_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None) + user_group_description = Column("user_group_description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None) users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + _group_data = Column("group_data", LargeBinary(), nullable=True) # JSON data members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined") users_group_to_perm = relationship('UserGroupToPerm', cascade='all') @@ -653,6 +804,23 @@ class UserGroup(Base, BaseModel): user = relationship('User') + @hybrid_property + def group_data(self): + if not self._group_data: + return {} + + try: + return json.loads(self._group_data) + except TypeError: + return {} + + @group_data.setter + def group_data(self, val): + try: + self._group_data = json.dumps(val) + except Exception: + log.error(traceback.format_exc()) + def __unicode__(self): return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.users_group_id, @@ -674,21 +842,29 @@ class UserGroup(Base, BaseModel): return q.scalar() @classmethod - def get(cls, users_group_id, cache=False): - users_group = cls.query() + def get(cls, user_group_id, cache=False): + user_group = cls.query() if cache: - users_group = users_group.options(FromCache("sql_cache_short", - "get_users_group_%s" % users_group_id)) - return users_group.get(users_group_id) - - def get_api_data(self): - users_group = self + user_group = user_group.options(FromCache("sql_cache_short", + "get_users_group_%s" % user_group_id)) + return user_group.get(user_group_id) + + def get_api_data(self, with_members=True): + user_group = self data = dict( - users_group_id=users_group.users_group_id, - group_name=users_group.users_group_name, - active=users_group.users_group_active, + users_group_id=user_group.users_group_id, + group_name=user_group.users_group_name, + group_description=user_group.user_group_description, + active=user_group.users_group_active, + owner=user_group.user.username, ) + if with_members: + members = [] + for user in user_group.members: + user = user.user + members.append(user.get_api_data()) + data['members'] = members return data @@ -697,7 +873,7 @@ class UserGroupMember(Base, BaseModel): __tablename__ = 'users_groups_members' __table_args__ = ( {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) @@ -717,16 +893,16 @@ class RepositoryField(Base, BaseModel): __table_args__ = ( UniqueConstraint('repository_id', 'field_key'), # no-multi field {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) - field_key = Column("field_key", String(250, convert_unicode=False, assert_unicode=None)) - field_label = Column("field_label", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) - field_value = Column("field_value", String(10000, convert_unicode=False, assert_unicode=None), nullable=False) - field_desc = Column("field_desc", String(1024, convert_unicode=False, assert_unicode=None), nullable=False) + field_key = Column("field_key", String(250, convert_unicode=False)) + field_label = Column("field_label", String(1024, convert_unicode=False), nullable=False) + field_value = Column("field_value", String(10000, convert_unicode=False), nullable=False) + field_desc = Column("field_desc", String(1024, convert_unicode=False), nullable=False) field_type = Column("field_type", String(256), nullable=False, unique=None) created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) @@ -756,23 +932,31 @@ class Repository(Base, BaseModel): UniqueConstraint('repo_name'), Index('r_repo_name_idx', 'repo_name'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) + DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}' + DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}' + + STATE_CREATED = 'repo_state_created' + STATE_PENDING = 'repo_state_pending' + STATE_ERROR = 'repo_state_error' repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) - repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) - clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) - repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + repo_name = Column("repo_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None) + repo_state = Column("repo_state", String(255), nullable=True) + + clone_uri = Column("clone_uri", String(255, convert_unicode=False), nullable=True, unique=False, default=None) + repo_type = Column("repo_type", String(255, convert_unicode=False), nullable=False, unique=False, default=None) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) private = Column("private", Boolean(), nullable=True, unique=None, default=None) enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True) enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True) - description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + description = Column("description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None) created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) - landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None) + _landing_revision = Column("landing_revision", String(255, convert_unicode=False), nullable=False, unique=False, default=None) enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) - _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) + _locked = Column("locked", String(255, convert_unicode=False), nullable=True, unique=False, default=None) _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) @@ -804,7 +988,24 @@ class Repository(Base, BaseModel): def __unicode__(self): return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, - self.repo_name) + safe_unicode(self.repo_name)) + + @hybrid_property + def landing_rev(self): + # always should return [rev_type, rev] + if self._landing_revision: + _rev_info = self._landing_revision.split(':') + if len(_rev_info) < 2: + _rev_info.insert(0, 'rev') + return [_rev_info[0], _rev_info[1]] + return [None, None] + + @landing_rev.setter + def landing_rev(self, val): + if ':' not in val: + raise ValueError('value must be delimited with `:` and consist ' + 'of :, got %s instead' % val) + self._landing_revision = val @hybrid_property def locked(self): @@ -823,7 +1024,7 @@ class Repository(Base, BaseModel): @hybrid_property def changeset_cache(self): - from rhodecode.lib.vcs.backends.base import EmptyChangeset + from kallithea.lib.vcs.backends.base import EmptyChangeset dummy = EmptyChangeset().__json__() if not self._changeset_cache: return dummy @@ -879,8 +1080,8 @@ class Repository(Base, BaseModel): :param cls: """ - q = Session().query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == cls.url_sep()) + q = Session().query(Ui)\ + .filter(Ui.ui_key == cls.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -929,7 +1130,7 @@ class Repository(Base, BaseModel): Returns base full path for that repository means where it actually exists on a filesystem """ - q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == + q = Session().query(Ui).filter(Ui.ui_key == Repository.url_sep()) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value @@ -967,7 +1168,7 @@ class Repository(Base, BaseModel): """ Creates an db based ui object for this repository """ - from rhodecode.lib.utils import make_ui + from kallithea.lib.utils import make_ui return make_ui('db', clear_session=False) @classmethod @@ -978,7 +1179,7 @@ class Repository(Base, BaseModel): :param cls: :param repo_name: """ - from rhodecode.lib.utils import is_valid_repo + from kallithea.lib.utils import is_valid_repo return is_valid_repo(repo_name, cls.base_path()) @@ -1008,8 +1209,8 @@ class Repository(Base, BaseModel): locked_date=time_to_datetime(self.locked[1]) \ if self.locked[1] else None ) - rc_config = RhodeCodeSetting.get_app_settings() - repository_fields = str2bool(rc_config.get('rhodecode_repository_fields')) + rc_config = Setting.get_app_settings() + repository_fields = str2bool(rc_config.get('repository_fields')) if repository_fields: for f in self.extra_fields: data[f.field_key_prefixed] = f.field_value @@ -1038,25 +1239,48 @@ class Repository(Base, BaseModel): def last_db_change(self): return self.updated_on + @property + def clone_uri_hidden(self): + clone_uri = self.clone_uri + if clone_uri: + import urlobject + url_obj = urlobject.URLObject(self.clone_uri) + if url_obj.password: + clone_uri = url_obj.with_password('*****') + return clone_uri + def clone_url(self, **override): from pylons import url - from urlparse import urlparse - import urllib - parsed_url = urlparse(url('home', qualified=True)) - default_clone_uri = '%(scheme)s://%(user)s%(pass)s%(netloc)s%(prefix)s%(path)s' - decoded_path = safe_unicode(urllib.unquote(parsed_url.path)) - args = { - 'user': '', - 'pass': '', - 'scheme': parsed_url.scheme, - 'netloc': parsed_url.netloc, - 'prefix': decoded_path, - 'path': self.repo_name - } - - args.update(override) - return default_clone_uri % args - + qualified_home_url = url('home', qualified=True) + + uri_tmpl = None + if 'with_id' in override: + uri_tmpl = self.DEFAULT_CLONE_URI_ID + del override['with_id'] + + if 'uri_tmpl' in override: + uri_tmpl = override['uri_tmpl'] + del override['uri_tmpl'] + + # we didn't override our tmpl from **overrides + if not uri_tmpl: + uri_tmpl = self.DEFAULT_CLONE_URI + try: + from pylons import tmpl_context as c + uri_tmpl = c.clone_uri_tmpl + except Exception: + # in any case if we call this outside of request context, + # ie, not having tmpl_context set up + pass + + return get_clone_url(uri_tmpl=uri_tmpl, + qualifed_home_url=qualified_home_url, + repo_name=self.repo_name, + repo_id=self.repo_id, **override) + + def set_state(self, state): + self.repo_state = state + Session().add(self) #========================================================================== # SCM PROPERTIES #========================================================================== @@ -1068,7 +1292,10 @@ class Repository(Base, BaseModel): """ Returns landing changeset, or if that doesn't exist returns the tip """ - cs = self.get_changeset(self.landing_rev) or self.get_changeset() + _rev_type, _rev = self.landing_rev + cs = self.get_changeset(_rev) + if isinstance(cs, EmptyChangeset): + return self.get_changeset() return cs def update_changeset_cache(self, cs_cache=None): @@ -1084,7 +1311,7 @@ class Repository(Base, BaseModel): :param cs_cache: """ - from rhodecode.lib.vcs.backends.base import BaseChangeset + from kallithea.lib.vcs.backends.base import BaseChangeset if cs_cache is None: cs_cache = EmptyChangeset() # use no-cache version here @@ -1168,7 +1395,7 @@ class Repository(Base, BaseModel): return grouped def _repo_size(self): - from rhodecode.lib import helpers as h + from kallithea.lib import helpers as h log.debug('calculating repository size...') return h.format_byte_size(self.scm_instance.size) @@ -1187,8 +1414,8 @@ class Repository(Base, BaseModel): @property def scm_instance(self): - import rhodecode - full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache')) + import kallithea + full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache')) if full_cache: return self.scm_instance_cached() return self.__get_instance() @@ -1233,6 +1460,8 @@ class Repository(Base, BaseModel): return repo + def __json__(self): + return dict(landing_rev = self.landing_rev) class RepoGroup(Base, BaseModel): __tablename__ = 'groups' @@ -1240,16 +1469,19 @@ class RepoGroup(Base, BaseModel): UniqueConstraint('group_name', 'group_parent_id'), CheckConstraint('group_id != group_parent_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) __mapper_args__ = {'order_by': 'group_name'} + SEP = ' » ' + group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) - group_name = Column("group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) + group_name = Column("group_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None) group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) - group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + group_description = Column("group_description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None) enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id') users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all') @@ -1265,21 +1497,23 @@ class RepoGroup(Base, BaseModel): self.group_name) @classmethod + def _generate_choice(cls, repo_group): + from webhelpers.html import literal as _literal + _name = lambda k: _literal(cls.SEP.join(k)) + return repo_group.group_id, _name(repo_group.full_path_splitted) + + @classmethod def groups_choices(cls, groups=None, show_empty_group=True): - from webhelpers.html import literal as _literal if not groups: groups = cls.query().all() repo_groups = [] if show_empty_group: repo_groups = [('-1', u'-- %s --' % _('top level'))] - sep = ' » ' - _name = lambda k: _literal(sep.join(k)) - - repo_groups.extend([(x.group_id, _name(x.full_path_splitted)) - for x in groups]) - - repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0]) + + repo_groups.extend([cls._generate_choice(x) for x in groups]) + + repo_groups = sorted(repo_groups, key=lambda t: t[1].split(cls.SEP)[0]) return repo_groups @classmethod @@ -1304,7 +1538,7 @@ class RepoGroup(Base, BaseModel): @property def parents(self): - parents_recursion_limit = 5 + parents_recursion_limit = 10 groups = [] if self.parent_group is None: return groups @@ -1319,8 +1553,8 @@ class RepoGroup(Base, BaseModel): break if cnt == parents_recursion_limit: # this will prevent accidental infinit loops - log.error('group nested more than %s' % - parents_recursion_limit) + log.error(('more than %s parents found for group %s, stopping ' + 'recursive parent fetching' % (parents_recursion_limit, self))) break groups.insert(0, gr) @@ -1399,16 +1633,32 @@ class RepoGroup(Base, BaseModel): self.parent_group else []) return RepoGroup.url_sep().join(path_prefix + [group_name]) + def get_api_data(self): + """ + Common function for generating api data + + """ + group = self + data = dict( + group_id=group.group_id, + group_name=group.group_name, + group_description=group.group_description, + parent_group=group.parent_group.group_name if group.parent_group else None, + repositories=[x.repo_name for x in group.repositories], + owner=group.user.username + ) + return data + class Permission(Base, BaseModel): __tablename__ = 'permissions' __table_args__ = ( Index('p_perm_name_idx', 'permission_name'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) PERMS = [ - ('hg.admin', _('RhodeCode Administrator')), + ('hg.admin', _('Kallithea Administrator')), ('repository.none', _('Repository no access')), ('repository.read', _('Repository read access')), @@ -1433,6 +1683,8 @@ class Permission(Base, BaseModel): ('hg.create.none', _('Repository creation disabled')), ('hg.create.repository', _('Repository creation enabled')), + ('hg.create.write_on_repogroup.true', _('Repository creation enabled with write permission to a repository group')), + ('hg.create.write_on_repogroup.false', _('Repository creation disabled with write permission to a repository group')), ('hg.fork.none', _('Repository forking disabled')), ('hg.fork.repository', _('Repository forking enabled')), @@ -1452,6 +1704,7 @@ class Permission(Base, BaseModel): 'group.read', 'usergroup.read', 'hg.create.repository', + 'hg.create.write_on_repogroup.true', 'hg.fork.repository', 'hg.register.manual_activate', 'hg.extern_activate.auto', @@ -1488,8 +1741,8 @@ class Permission(Base, BaseModel): } permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) - permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + permission_name = Column("permission_name", String(255, convert_unicode=False), nullable=True, unique=None, default=None) + permission_longname = Column("permission_longname", String(255, convert_unicode=False), nullable=True, unique=None, default=None) def __unicode__(self): return u"<%s('%s:%s')>" % ( @@ -1533,7 +1786,7 @@ class UserRepoToPerm(Base, BaseModel): __table_args__ = ( UniqueConstraint('user_id', 'repository_id', 'permission_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) @@ -1562,7 +1815,7 @@ class UserUserGroupToPerm(Base, BaseMode __table_args__ = ( UniqueConstraint('user_id', 'user_group_id', 'permission_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) @@ -1591,7 +1844,7 @@ class UserToPerm(Base, BaseModel): __table_args__ = ( UniqueConstraint('user_id', 'permission_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) @@ -1609,7 +1862,7 @@ class UserGroupRepoToPerm(Base, BaseMode __table_args__ = ( UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) @@ -1639,7 +1892,7 @@ class UserGroupUserGroupToPerm(Base, Bas UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'), CheckConstraint('target_user_group_id != user_group_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) @@ -1668,7 +1921,7 @@ class UserGroupToPerm(Base, BaseModel): __table_args__ = ( UniqueConstraint('users_group_id', 'permission_id',), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) @@ -1683,7 +1936,7 @@ class UserRepoGroupToPerm(Base, BaseMode __table_args__ = ( UniqueConstraint('user_id', 'group_id', 'permission_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) @@ -1695,13 +1948,22 @@ class UserRepoGroupToPerm(Base, BaseMode group = relationship('RepoGroup') permission = relationship('Permission') + @classmethod + def create(cls, user, repository_group, permission): + n = cls() + n.user = user + n.group = repository_group + n.permission = permission + Session().add(n) + return n + class UserGroupRepoGroupToPerm(Base, BaseModel): __tablename__ = 'users_group_repo_group_to_perm' __table_args__ = ( UniqueConstraint('users_group_id', 'group_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) @@ -1713,13 +1975,22 @@ class UserGroupRepoGroupToPerm(Base, Bas permission = relationship('Permission') group = relationship('RepoGroup') + @classmethod + def create(cls, user_group, repository_group, permission): + n = cls() + n.users_group = user_group + n.group = repository_group + n.permission = permission + Session().add(n) + return n + class Statistics(Base, BaseModel): __tablename__ = 'statistics' __table_args__ = ( UniqueConstraint('repository_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) @@ -1737,7 +2008,7 @@ class UserFollowing(Base, BaseModel): UniqueConstraint('user_id', 'follows_repository_id'), UniqueConstraint('user_id', 'follows_user_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) @@ -1762,14 +2033,14 @@ class CacheInvalidation(Base, BaseModel) UniqueConstraint('cache_key'), Index('key_idx', 'cache_key'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) # cache_id, not used cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) # cache_key as created by _get_cache_key - cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + cache_key = Column("cache_key", String(255, convert_unicode=False), nullable=True, unique=None, default=None) # cache_args is a repo_name - cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + cache_args = Column("cache_args", String(255, convert_unicode=False), nullable=True, unique=None, default=None) # instance sets cache_active True when it is caching, # other instances set cache_active to False to indicate that this cache is invalid cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False) @@ -1820,23 +2091,27 @@ class CacheInvalidation(Base, BaseModel) Wrapper for generating a unique cache key for this instance and "key". key must / will start with a repo_name which will be stored in .cache_args . """ - import rhodecode - prefix = rhodecode.CONFIG.get('instance_id', '') + import kallithea + prefix = kallithea.CONFIG.get('instance_id', '') return "%s%s" % (prefix, key) @classmethod - def set_invalidate(cls, repo_name): + def set_invalidate(cls, repo_name, delete=False): """ Mark all caches of a repo as invalid in the database. """ inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all() - + log.debug('for repo %s got %s invalidation objects' + % (safe_str(repo_name), inv_objs)) try: for inv_obj in inv_objs: log.debug('marking %s key for invalidation based on repo_name=%s' % (inv_obj, safe_str(repo_name))) - inv_obj.cache_active = False - Session().add(inv_obj) + if delete: + Session().delete(inv_obj) + else: + inv_obj.cache_active = False + Session().add(inv_obj) Session().commit() except Exception: log.error(traceback.format_exc()) @@ -1884,7 +2159,7 @@ class ChangesetComment(Base, BaseModel): __table_args__ = ( Index('cc_revision_idx', 'revision'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) @@ -1928,7 +2203,7 @@ class ChangesetStatus(Base, BaseModel): Index('cs_version_idx', 'version'), UniqueConstraint('repo_id', 'revision', 'version'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed' STATUS_APPROVED = 'approved' @@ -1976,7 +2251,7 @@ class PullRequest(Base, BaseModel): __tablename__ = 'pull_requests' __table_args__ = ( {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) # values for .status @@ -2031,7 +2306,7 @@ class PullRequest(Base, BaseModel): def __json__(self): return dict( - revisions=self.revisions + revisions=self.revisions ) @@ -2039,7 +2314,7 @@ class PullRequestReviewers(Base, BaseMod __tablename__ = 'pull_request_reviewers' __table_args__ = ( {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) def __init__(self, user=None, pull_request=None): @@ -2059,7 +2334,7 @@ class Notification(Base, BaseModel): __table_args__ = ( Index('notification_type_idx', 'type'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) TYPE_CHANGESET_COMMENT = u'cs_comment' @@ -2107,7 +2382,7 @@ class Notification(Base, BaseModel): @property def description(self): - from rhodecode.model.notification import NotificationModel + from kallithea.model.notification import NotificationModel return NotificationModel().make_description(self) @@ -2116,7 +2391,7 @@ class UserNotification(Base, BaseModel): __table_args__ = ( UniqueConstraint('user_id', 'notification_id'), {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'} + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True} ) user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True) notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True) @@ -2142,6 +2417,7 @@ class Gist(Base, BaseModel): ) GIST_PUBLIC = u'public' GIST_PRIVATE = u'private' + DEFAULT_FILENAME = u'gistfile1.txt' gist_id = Column('gist_id', Integer(), primary_key=True) gist_access_id = Column('gist_access_id', Unicode(250)) @@ -2154,6 +2430,9 @@ class Gist(Base, BaseModel): owner = relationship('User') + def __repr__(self): + return '' % (self.gist_type, self.gist_access_id) + @classmethod def get_or_404(cls, id_): res = cls.query().filter(cls.gist_access_id == id_).scalar() @@ -2166,8 +2445,8 @@ class Gist(Base, BaseModel): return cls.query().filter(cls.gist_access_id == gist_access_id).scalar() def gist_url(self): - import rhodecode - alias_url = rhodecode.CONFIG.get('gist_alias_url') + import kallithea + alias_url = kallithea.CONFIG.get('gist_alias_url') if alias_url: return alias_url.replace('{gistid}', self.gist_access_id) @@ -2181,9 +2460,9 @@ class Gist(Base, BaseModel): :param cls: """ - from rhodecode.model.gist import GIST_STORE_LOC - q = Session().query(RhodeCodeUi)\ - .filter(RhodeCodeUi.ui_key == URL_SEP) + from kallithea.model.gist import GIST_STORE_LOC + q = Session().query(Ui)\ + .filter(Ui.ui_key == URL_SEP) q = q.options(FromCache("sql_cache_short", "repository_repo_path")) return os.path.join(q.one().ui_value, GIST_STORE_LOC) @@ -2212,7 +2491,7 @@ class Gist(Base, BaseModel): @property def scm_instance(self): - from rhodecode.lib.vcs import get_repo + from kallithea.lib.vcs import get_repo base_path = self.base_path() return get_repo(os.path.join(*map(safe_str, [base_path, self.gist_access_id]))) @@ -2222,7 +2501,7 @@ class DbMigrateVersion(Base, BaseModel): __tablename__ = 'db_migrate_version' __table_args__ = ( {'extend_existing': True, 'mysql_engine': 'InnoDB', - 'mysql_charset': 'utf8'}, + 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}, ) repository_id = Column('repository_id', String(250), primary_key=True) repository_path = Column('repository_path', Text) diff --git a/rhodecode/model/forms.py b/kallithea/model/forms.py rename from rhodecode/model/forms.py rename to kallithea/model/forms.py --- a/rhodecode/model/forms.py +++ b/kallithea/model/forms.py @@ -1,4 +1,18 @@ -""" this is forms validation classes +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +this is forms validation classes http://formencode.org/module-formencode.validators.html for list off all availible validators @@ -26,8 +40,8 @@ from formencode import All from pylons.i18n.translation import _ -from rhodecode.model import validators as v -from rhodecode import BACKENDS +from kallithea import BACKENDS +from kallithea.model import validators as v log = logging.getLogger(__name__) @@ -58,6 +72,20 @@ class LoginForm(formencode.Schema): chained_validators = [v.ValidAuth()] +def PasswordChangeForm(username): + class _PasswordChangeForm(formencode.Schema): + allow_extra_fields = True + filter_extra_fields = True + + current_password = v.ValidOldPassword(username)(not_empty=True) + new_password = All(v.ValidPassword(), v.UnicodeString(strip=False, min=6)) + new_password_confirmation = All(v.ValidPassword(), v.UnicodeString(strip=False, min=6)) + + chained_validators = [v.ValidPasswordsMatch('new_password', + 'new_password_confirmation')] + return _PasswordChangeForm + + def UserForm(edit=False, old_data={}): class _UserForm(formencode.Schema): allow_extra_fields = True @@ -88,9 +116,9 @@ def UserForm(edit=False, old_data={}): firstname = v.UnicodeString(strip=True, min=1, not_empty=False) lastname = v.UnicodeString(strip=True, min=1, not_empty=False) email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data)) - + extern_name = v.UnicodeString(strip=True) + extern_type = v.UnicodeString(strip=True) chained_validators = [v.ValidPasswordsMatch()] - return _UserForm @@ -103,6 +131,8 @@ def UserGroupForm(edit=False, old_data={ v.UnicodeString(strip=True, min=1, not_empty=True), v.ValidUserGroup(edit, old_data) ) + user_group_description = v.UnicodeString(strip=True, min=1, + not_empty=False) users_group_active = v.StringBoolean(if_missing=False) @@ -115,16 +145,19 @@ def UserGroupForm(edit=False, old_data={ return _UserGroupForm -def ReposGroupForm(edit=False, old_data={}, available_groups=[], +def RepoGroupForm(edit=False, old_data={}, available_groups=[], can_create_in_root=False): - class _ReposGroupForm(formencode.Schema): + class _RepoGroupForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = False group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True), - v.SlugifyName()) + v.SlugifyName(), + v.ValidRegex(msg=_('Name must not contain only digits'))(r'(?!^\d+$)^.+$')) group_description = v.UnicodeString(strip=True, min=1, - not_empty=False) + not_empty=False) + group_copy_permissions = v.StringBoolean(if_missing=False) + if edit: #FIXME: do a special check that we cannot move a group to one of #it's children @@ -134,9 +167,9 @@ def ReposGroupForm(edit=False, old_data= testValueList=True, if_missing=None, not_empty=True)) enable_locking = v.StringBoolean(if_missing=False) - chained_validators = [v.ValidReposGroup(edit, old_data)] + chained_validators = [v.ValidRepoGroup(edit, old_data)] - return _ReposGroupForm + return _RepoGroupForm def RegisterForm(edit=False, old_data={}): @@ -187,6 +220,7 @@ def RepoForm(edit=False, old_data={}, su repo_description = v.UnicodeString(strip=True, min=1, not_empty=False) repo_private = v.StringBoolean(if_missing=False) repo_landing_rev = v.OneOf(landing_revs, hideList=True) + repo_copy_permissions = v.StringBoolean(if_missing=False) clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False)) repo_enable_statistics = v.StringBoolean(if_missing=False) @@ -196,6 +230,7 @@ def RepoForm(edit=False, old_data={}, su if edit: #this is repo owner user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser()) + clone_uri_change = v.UnicodeString(not_empty=False, if_missing=v.Missing) chained_validators = [v.ValidCloneUri(), v.ValidRepoName(edit, old_data)] @@ -210,11 +245,11 @@ def RepoPermsForm(): return _RepoPermsForm -def RepoGroupPermsForm(): +def RepoGroupPermsForm(valid_recursive_choices): class _RepoGroupPermsForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = False - recursive = v.StringBoolean(if_missing=False) + recursive = v.OneOf(valid_recursive_choices) chained_validators = [v.ValidPerms(type_='repo_group')] return _RepoGroupPermsForm @@ -268,9 +303,11 @@ def ApplicationSettingsForm(): class _ApplicationSettingsForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = False - rhodecode_title = v.UnicodeString(strip=True, min=1, not_empty=True) - rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True) - rhodecode_ga_code = v.UnicodeString(strip=True, min=1, not_empty=False) + title = v.UnicodeString(strip=True, not_empty=False) + realm = v.UnicodeString(strip=True, min=1, not_empty=True) + ga_code = v.UnicodeString(strip=True, min=1, not_empty=False) + captcha_public_key = v.UnicodeString(strip=True, min=1, not_empty=False) + captcha_private_key = v.UnicodeString(strip=True, min=1, not_empty=False) return _ApplicationSettingsForm @@ -279,14 +316,18 @@ def ApplicationVisualisationForm(): class _ApplicationVisualisationForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = False - rhodecode_show_public_icon = v.StringBoolean(if_missing=False) - rhodecode_show_private_icon = v.StringBoolean(if_missing=False) - rhodecode_stylify_metatags = v.StringBoolean(if_missing=False) + show_public_icon = v.StringBoolean(if_missing=False) + show_private_icon = v.StringBoolean(if_missing=False) + stylify_metatags = v.StringBoolean(if_missing=False) - rhodecode_repository_fields = v.StringBoolean(if_missing=False) - rhodecode_lightweight_journal = v.StringBoolean(if_missing=False) - rhodecode_dashboard_items = v.Int(min=5, not_empty=True) - rhodecode_show_version = v.StringBoolean(if_missing=False) + repository_fields = v.StringBoolean(if_missing=False) + lightweight_journal = v.StringBoolean(if_missing=False) + dashboard_items = v.Int(min=5, not_empty=True) + admin_grid_items = v.Int(min=5, not_empty=True) + show_version = v.StringBoolean(if_missing=False) + use_gravatar = v.StringBoolean(if_missing=False) + gravatar_url = v.UnicodeString(min=3) + clone_uri_tmpl = v.UnicodeString(min=3) return _ApplicationVisualisationForm @@ -314,8 +355,9 @@ def ApplicationUiSettingsForm(): def DefaultPermissionsForm(repo_perms_choices, group_perms_choices, user_group_perms_choices, create_choices, - repo_group_create_choices, user_group_create_choices, - fork_choices, register_choices, extern_activate_choices): + create_on_write_choices, repo_group_create_choices, + user_group_create_choices, fork_choices, + register_choices, extern_activate_choices): class _DefaultPermissionsForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = True @@ -328,6 +370,7 @@ def DefaultPermissionsForm(repo_perms_ch default_user_group_perm = v.OneOf(user_group_perms_choices) default_repo_create = v.OneOf(create_choices) + create_on_write = v.OneOf(create_on_write_choices) default_user_group_create = v.OneOf(user_group_create_choices) #default_repo_group_create = v.OneOf(repo_group_create_choices) #not impl. yet default_fork = v.OneOf(fork_choices) @@ -365,6 +408,42 @@ def DefaultsForm(edit=False, old_data={} return _DefaultsForm +def AuthSettingsForm(current_active_modules): + class _AuthSettingsForm(formencode.Schema): + allow_extra_fields = True + filter_extra_fields = True + auth_plugins = All(v.ValidAuthPlugins(), + v.UniqueListFromString()(not_empty=True)) + + def __init__(self, *args, **kwargs): + # The auth plugins tell us what form validators they use + if current_active_modules: + import kallithea.lib.auth_modules + from kallithea.lib.auth_modules import LazyFormencode + for module in current_active_modules: + plugin = kallithea.lib.auth_modules.loadplugin(module) + plugin_name = plugin.name + for sv in plugin.plugin_settings(): + newk = "auth_%s_%s" % (plugin_name, sv["name"]) + # can be a LazyFormencode object from plugin settings + validator = sv["validator"] + if isinstance(validator, LazyFormencode): + validator = validator() + #init all lazy validators from formencode.All + if isinstance(validator, All): + init_validators = [] + for validator in validator.validators: + if isinstance(validator, LazyFormencode): + validator = validator() + init_validators.append(validator) + validator.validators = init_validators + + self.add_field(newk, validator) + formencode.Schema.__init__(self, *args, **kwargs) + + return _AuthSettingsForm + + def LdapSettingsForm(tls_reqcert_choices, search_scope_choices, tls_kind_choices): class _LdapSettingsForm(formencode.Schema): @@ -412,8 +491,8 @@ def PullRequestForm(repo_id): other_repo = v.UnicodeString(strip=True, required=True) other_ref = v.UnicodeString(strip=True, required=True) revisions = All(#v.NotReviewedRevisions(repo_id)(), - v.UniqueList(not_empty=True)) - review_members = v.UniqueList(not_empty=True) + v.UniqueList()(not_empty=True)) + review_members = v.UniqueList()(not_empty=True) pullrequest_title = v.UnicodeString(strip=True, required=True) pullrequest_desc = v.UnicodeString(strip=True, required=False) diff --git a/rhodecode/model/gist.py b/kallithea/model/gist.py rename from rhodecode/model/gist.py rename to kallithea/model/gist.py --- a/rhodecode/model/gist.py +++ b/kallithea/model/gist.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.gist - ~~~~~~~~~~~~~~~~~~~~ - - gist model for RhodeCode - - :created_on: May 9, 2013 - :author: marcink - :copyright: (C) 2011-2013 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.gist +~~~~~~~~~~~~~~~~~~~~ + +gist model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: May 9, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from __future__ import with_statement import os import time @@ -30,14 +33,14 @@ import traceback import shutil from pylons.i18n.translation import _ -from rhodecode.lib.utils2 import safe_unicode, unique_id, safe_int, \ +from kallithea.lib.utils2 import safe_unicode, unique_id, safe_int, \ time_to_datetime, safe_str, AttributeDict -from rhodecode.lib.compat import json -from rhodecode.lib import helpers as h -from rhodecode.model import BaseModel -from rhodecode.model.db import Gist -from rhodecode.model.repo import RepoModel -from rhodecode.model.scm import ScmModel +from kallithea.lib.compat import json +from kallithea.lib import helpers as h +from kallithea.model import BaseModel +from kallithea.model.db import Gist +from kallithea.model.repo import RepoModel +from kallithea.model.scm import ScmModel log = logging.getLogger(__name__) @@ -46,6 +49,7 @@ GIST_METADATA_FILE = '.rc_gist_metadata' class GistModel(BaseModel): + cls = Gist def _get_gist(self, gist): """ @@ -53,8 +57,7 @@ class GistModel(BaseModel): :param gist: GistID, gist_access_id, or Gist instance """ - return self._get_instance(Gist, gist, - callback=Gist.get_by_access_id) + return self._get_instance(Gist, gist, callback=Gist.get_by_access_id) def __delete_gist(self, gist): """ @@ -64,23 +67,39 @@ class GistModel(BaseModel): """ root_path = RepoModel().repos_path rm_path = os.path.join(root_path, GIST_STORE_LOC, gist.gist_access_id) - log.info("Removing %s" % (rm_path)) + log.info("Removing %s" % (rm_path,)) shutil.rmtree(rm_path) + def _store_metadata(self, repo, gist_id, gist_access_id, user_id, gist_type, + gist_expires): + """ + store metadata inside the gist, this can be later used for imports + or gist identification + """ + metadata = { + 'metadata_version': '1', + 'gist_db_id': gist_id, + 'gist_access_id': gist_access_id, + 'gist_owner_id': user_id, + 'gist_type': gist_type, + 'gist_expires': gist_expires, + 'gist_updated': time.time(), + } + with open(os.path.join(repo.path, '.hg', GIST_METADATA_FILE), 'wb') as f: + f.write(json.dumps(metadata)) + def get_gist(self, gist): return self._get_gist(gist) - def get_gist_files(self, gist_access_id): + def get_gist_files(self, gist_access_id, revision=None): """ Get files for given gist :param gist_access_id: """ repo = Gist.get_by_access_id(gist_access_id) - cs = repo.scm_instance.get_changeset() - return ( - cs, [n for n in cs.get_node('/')] - ) + cs = repo.scm_instance.get_changeset(revision) + return cs, [n for n in cs.get_node('/')] def create(self, description, owner, gist_mapping, gist_type=Gist.GIST_PUBLIC, lifetime=-1): @@ -92,6 +111,7 @@ class GistModel(BaseModel): :param gist_type: type of gist private/public :param lifetime: in minutes, -1 == forever """ + owner = self._get_user(owner) gist_id = safe_unicode(unique_id(20)) lifetime = safe_int(lifetime, -1) gist_expires = time.time() + (lifetime * 60) if lifetime != -1 else -1 @@ -115,8 +135,8 @@ class GistModel(BaseModel): gist_repo_path = os.path.join(GIST_STORE_LOC, gist_id) log.debug('Creating new %s GIST repo in %s' % (gist_type, gist_repo_path)) - repo = RepoModel()._create_repo(repo_name=gist_repo_path, alias='hg', - parent=None) + repo = RepoModel()._create_filesystem_repo( + repo_name=gist_id, repo_type='hg', repo_group=GIST_STORE_LOC) processed_mapping = {} for filename in gist_mapping: @@ -127,7 +147,8 @@ class GistModel(BaseModel): #TODO: expand support for setting explicit lexers # if lexer is None: # try: -# lexer = pygments.lexers.guess_lexer_for_filename(filename,content) +# guess_lexer = pygments.lexers.guess_lexer_for_filename +# lexer = guess_lexer(filename,content) # except pygments.util.ClassNotFound: # lexer = 'text' processed_mapping[filename] = {'content': content} @@ -137,7 +158,7 @@ class GistModel(BaseModel): message += 's: ' if len(processed_mapping) > 1 else ': ' message += ', '.join([x for x in processed_mapping]) - #fake RhodeCode Repository object + #fake Kallithea Repository object fake_repo = AttributeDict(dict( repo_name=gist_repo_path, scm_instance_no_cache=lambda: repo, @@ -148,29 +169,74 @@ class GistModel(BaseModel): nodes=processed_mapping, trigger_push_hook=False ) - # store metadata inside the gist, this can be later used for imports - # or gist identification - metadata = { - 'gist_db_id': gist.gist_id, - 'gist_access_id': gist.gist_access_id, - 'gist_owner_id': owner.user_id, - 'gist_type': gist.gist_type, - 'gist_exipres': gist.gist_expires - } - with open(os.path.join(repo.path, '.hg', GIST_METADATA_FILE), 'wb') as f: - f.write(json.dumps(metadata)) + + self._store_metadata(repo, gist.gist_id, gist.gist_access_id, + owner.user_id, gist.gist_type, gist.gist_expires) return gist def delete(self, gist, fs_remove=True): gist = self._get_gist(gist) - try: self.sa.delete(gist) if fs_remove: self.__delete_gist(gist) else: log.debug('skipping removal from filesystem') - except Exception: log.error(traceback.format_exc()) raise + + def update(self, gist, description, owner, gist_mapping, gist_type, + lifetime): + gist = self._get_gist(gist) + gist_repo = gist.scm_instance + + lifetime = safe_int(lifetime, -1) + if lifetime == 0: # preserve old value + gist_expires = gist.gist_expires + else: + gist_expires = time.time() + (lifetime * 60) if lifetime != -1 else -1 + + #calculate operation type based on given data + gist_mapping_op = {} + for k, v in gist_mapping.items(): + # add, mod, del + if not v['org_filename'] and v['filename']: + op = 'add' + elif v['org_filename'] and not v['filename']: + op = 'del' + else: + op = 'mod' + + v['op'] = op + gist_mapping_op[k] = v + + gist.gist_description = description + gist.gist_expires = gist_expires + gist.owner = owner + gist.gist_type = gist_type + self.sa.add(gist) + self.sa.flush() + + message = 'updated file' + message += 's: ' if len(gist_mapping) > 1 else ': ' + message += ', '.join([x for x in gist_mapping]) + + #fake Kallithea Repository object + fake_repo = AttributeDict(dict( + repo_name=gist_repo.path, + scm_instance_no_cache=lambda: gist_repo, + )) + + self._store_metadata(gist_repo, gist.gist_id, gist.gist_access_id, + owner.user_id, gist.gist_type, gist.gist_expires) + + ScmModel().update_nodes( + user=owner.user_id, + repo=fake_repo, + message=message, + nodes=gist_mapping_op, + trigger_push_hook=False + ) + + return gist diff --git a/rhodecode/model/meta.py b/kallithea/model/meta.py rename from rhodecode/model/meta.py rename to kallithea/model/meta.py --- a/rhodecode/model/meta.py +++ b/kallithea/model/meta.py @@ -1,9 +1,24 @@ -"""SQLAlchemy Metadata and Session object""" +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +SQLAlchemy Metadata and Session object +""" from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import scoped_session, sessionmaker from beaker import cache -from rhodecode.lib import caching_query +from kallithea.lib import caching_query # Beaker CacheManager. A home base for cache configurations. diff --git a/rhodecode/model/notification.py b/kallithea/model/notification.py rename from rhodecode/model/notification.py rename to kallithea/model/notification.py --- a/rhodecode/model/notification.py +++ b/kallithea/model/notification.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.notification - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Model for notifications - - - :created_on: Nov 20, 2011 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,6 +11,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.notification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Model for notifications + + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Nov 20, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import os import logging @@ -31,11 +34,11 @@ import traceback from pylons import tmpl_context as c from pylons.i18n.translation import _ -import rhodecode -from rhodecode.lib import helpers as h -from rhodecode.model import BaseModel -from rhodecode.model.db import Notification, User, UserNotification -from rhodecode.model.meta import Session +import kallithea +from kallithea.lib import helpers as h +from kallithea.model import BaseModel +from kallithea.model.db import Notification, User, UserNotification +from kallithea.model.meta import Session log = logging.getLogger(__name__) @@ -72,7 +75,7 @@ class NotificationModel(BaseModel): :param email_kwargs: additional dict to pass as args to email template :param email_subject: use given subject as email subject """ - from rhodecode.lib.celerylib import tasks, run_task + from kallithea.lib.celerylib import tasks, run_task if recipients and not getattr(recipients, '__iter__', False): raise Exception('recipients must be a list or iterable') @@ -228,7 +231,7 @@ class NotificationModel(BaseModel): _n.TYPE_CHANGESET_COMMENT: _('%(user)s commented on changeset at %(when)s'), _n.TYPE_MESSAGE: _('%(user)s sent message at %(when)s'), _n.TYPE_MENTION: _('%(user)s mentioned you at %(when)s'), - _n.TYPE_REGISTRATION: _('%(user)s registered in RhodeCode at %(when)s'), + _n.TYPE_REGISTRATION: _('%(user)s registered in Kallithea at %(when)s'), _n.TYPE_PULL_REQUEST: _('%(user)s opened new pull request at %(when)s'), _n.TYPE_PULL_REQUEST_COMMENT: _('%(user)s commented on pull request at %(when)s') } @@ -255,18 +258,19 @@ class EmailNotificationModel(BaseModel): TYPE_DEFAULT = 'default' def __init__(self): - self._template_root = rhodecode.CONFIG['pylons.paths']['templates'][0] - self._tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup - + super(EmailNotificationModel, self).__init__() + self._template_root = kallithea.CONFIG['pylons.paths']['templates'][0] + self._tmpl_lookup = kallithea.CONFIG['pylons.app_globals'].mako_lookup self.email_types = { - self.TYPE_CHANGESET_COMMENT: 'email_templates/changeset_comment.html', - self.TYPE_PASSWORD_RESET: 'email_templates/password_reset.html', - self.TYPE_REGISTRATION: 'email_templates/registration.html', - self.TYPE_DEFAULT: 'email_templates/default.html', - self.TYPE_PULL_REQUEST: 'email_templates/pull_request.html', - self.TYPE_PULL_REQUEST_COMMENT: 'email_templates/pull_request_comment.html', + self.TYPE_CHANGESET_COMMENT: 'email_templates/changeset_comment.html', + self.TYPE_PASSWORD_RESET: 'email_templates/password_reset.html', + self.TYPE_REGISTRATION: 'email_templates/registration.html', + self.TYPE_DEFAULT: 'email_templates/default.html', + self.TYPE_PULL_REQUEST: 'email_templates/pull_request.html', + self.TYPE_PULL_REQUEST_COMMENT: 'email_templates/pull_request_comment.html', } + def get_email_tmpl(self, type_, **kwargs): """ return generated template for email based on given type diff --git a/rhodecode/model/permission.py b/kallithea/model/permission.py rename from rhodecode/model/permission.py rename to kallithea/model/permission.py --- a/rhodecode/model/permission.py +++ b/kallithea/model/permission.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.permission - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - permissions model for RhodeCode - - :created_on: Aug 20, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,23 +11,37 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.permission +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +permissions model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Aug 20, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import traceback from sqlalchemy.exc import DatabaseError -from rhodecode.model import BaseModel -from rhodecode.model.db import User, Permission, UserToPerm, UserRepoToPerm,\ +from kallithea.model import BaseModel +from kallithea.model.db import User, Permission, UserToPerm, UserRepoToPerm,\ UserRepoGroupToPerm, UserUserGroupToPerm -from rhodecode.lib.utils2 import str2bool +from kallithea.lib.utils2 import str2bool log = logging.getLogger(__name__) class PermissionModel(BaseModel): """ - Permissions model for RhodeCode + Permissions model for Kallithea """ cls = Permission @@ -54,9 +57,10 @@ class PermissionModel(BaseModel): new_perm.permission_longname = p[0] #translation err with p[1] self.sa.add(new_perm) - def create_default_permissions(self, user): + def create_default_permissions(self, user, force=False): """ - Creates only missing default permissions for user + Creates only missing default permissions for user, if force is set it + resets the default permissions for that user :param user: """ @@ -77,6 +81,11 @@ class PermissionModel(BaseModel): log.debug('GOT ALREADY DEFINED:%s' % perms) DEFAULT_PERMS = Permission.DEFAULT_USER_PERMISSIONS + if force: + for perm in perms: + self.sa.delete(perm) + self.sa.commit() + defined_perms_groups = [] # for every default permission that needs to be created, we check if # it's group is already defined, if it's not we create default perm for perm_name in DEFAULT_PERMS: @@ -92,7 +101,7 @@ class PermissionModel(BaseModel): try: # stage 1 set anonymous access - if perm_user.username == 'default': + if perm_user.username == User.DEFAULT_USER: perm_user.active = str2bool(form_result['anonymous']) self.sa.add(perm_user) @@ -112,12 +121,15 @@ class PermissionModel(BaseModel): for p in u2p: self.sa.delete(p) #create fresh set of permissions - for def_perm_key in ['default_repo_perm', 'default_group_perm', + for def_perm_key in ['default_repo_perm', + 'default_group_perm', 'default_user_group_perm', 'default_repo_create', + 'create_on_write', # special case for create repos on write access to group #'default_repo_group_create', #not implemented yet 'default_user_group_create', - 'default_fork', 'default_register', + 'default_fork', + 'default_register', 'default_extern_activate']: p = _make_new(perm_user, form_result[def_perm_key]) self.sa.add(p) diff --git a/rhodecode/model/pull_request.py b/kallithea/model/pull_request.py rename from rhodecode/model/pull_request.py rename to kallithea/model/pull_request.py --- a/rhodecode/model/pull_request.py +++ b/kallithea/model/pull_request.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.pull_request - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - pull request model for RhodeCode - - :created_on: Jun 6, 2012 - :author: marcink - :copyright: (C) 2012-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,19 +11,32 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.pull_request +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +pull request model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jun 6, 2012 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" import logging import datetime from pylons.i18n.translation import _ -from rhodecode.model.meta import Session -from rhodecode.lib import helpers as h -from rhodecode.model import BaseModel -from rhodecode.model.db import PullRequest, PullRequestReviewers, Notification,\ +from kallithea.model.meta import Session +from kallithea.lib import helpers as h +from kallithea.model import BaseModel +from kallithea.model.db import PullRequest, PullRequestReviewers, Notification,\ ChangesetStatus -from rhodecode.model.notification import NotificationModel -from rhodecode.lib.utils2 import safe_unicode +from kallithea.model.notification import NotificationModel +from kallithea.lib.utils2 import safe_unicode log = logging.getLogger(__name__) @@ -63,7 +65,7 @@ class PullRequestModel(BaseModel): def create(self, created_by, org_repo, org_ref, other_repo, other_ref, revisions, reviewers, title, description=None): - from rhodecode.model.changeset_status import ChangesetStatusModel + from kallithea.model.changeset_status import ChangesetStatusModel created_by_user = self._get_user(created_by) org_repo = self._get_repo(org_repo) diff --git a/rhodecode/model/repo.py b/kallithea/model/repo.py rename from rhodecode/model/repo.py rename to kallithea/model/repo.py --- a/rhodecode/model/repo.py +++ b/kallithea/model/repo.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.repo - ~~~~~~~~~~~~~~~~~~~~ - - Repository model for rhodecode - - :created_on: Jun 5, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,28 +11,46 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.repo +~~~~~~~~~~~~~~~~~~~~ + +Repository model for kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jun 5, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" + from __future__ import with_statement import os import shutil import logging import traceback from datetime import datetime +from kallithea.lib.utils import make_ui -from rhodecode.lib.vcs.backends import get_backend -from rhodecode.lib.compat import json -from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode,\ - remove_prefix, obfuscate_url_pw, get_current_rhodecode_user -from rhodecode.lib.caching_query import FromCache -from rhodecode.lib.hooks import log_create_repository, log_delete_repository +from kallithea.lib.vcs.backends import get_backend +from kallithea.lib.compat import json +from kallithea.lib.utils2 import LazyProperty, safe_str, safe_unicode, \ + remove_prefix, obfuscate_url_pw, get_current_authuser +from kallithea.lib.caching_query import FromCache +from kallithea.lib.hooks import log_create_repository, log_delete_repository -from rhodecode.model import BaseModel -from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \ - Statistics, UserGroup, UserGroupRepoToPerm, RhodeCodeUi, RepoGroup,\ - RhodeCodeSetting, RepositoryField -from rhodecode.lib import helpers as h -from rhodecode.lib.auth import HasRepoPermissionAny, HasUserGroupPermissionAny -from rhodecode.lib.exceptions import AttachedForksError -from rhodecode.model.scm import UserGroupList +from kallithea.model import BaseModel +from kallithea.model.db import Repository, UserRepoToPerm, UserGroupRepoToPerm, \ + UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission, \ + Statistics, UserGroup, Ui, RepoGroup, \ + Setting, RepositoryField + +from kallithea.lib import helpers as h +from kallithea.lib.auth import HasRepoPermissionAny, HasUserGroupPermissionAny +from kallithea.lib.exceptions import AttachedForksError +from kallithea.model.scm import UserGroupList log = logging.getLogger(__name__) @@ -57,8 +64,8 @@ class RepoModel(BaseModel): return self._get_instance(UserGroup, users_group, callback=UserGroup.get_by_group_name) - def _get_repo_group(self, repos_group): - return self._get_instance(RepoGroup, repos_group, + def _get_repo_group(self, repo_group): + return self._get_instance(RepoGroup, repo_group, callback=RepoGroup.get_by_group_name) def _create_default_perms(self, repository, private): @@ -86,11 +93,11 @@ class RepoModel(BaseModel): Gets the repositories root path from database """ - q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one() + q = self.sa.query(Ui).filter(Ui.ui_key == '/').one() return q.ui_value def get(self, repo_id, cache=False): - repo = self.sa.query(Repository)\ + repo = self.sa.query(Repository) \ .filter(Repository.repo_id == repo_id) if cache: @@ -102,7 +109,7 @@ class RepoModel(BaseModel): return self._get_repo(repository) def get_by_repo_name(self, repo_name, cache=False): - repo = self.sa.query(Repository)\ + repo = self.sa.query(Repository) \ .filter(Repository.repo_name == repo_name) if cache: @@ -116,7 +123,7 @@ class RepoModel(BaseModel): :param user: """ - from rhodecode.lib.auth import AuthUser + from kallithea.lib.auth import AuthUser user = self._get_user(user) repos = AuthUser(user_id=user.user_id).permissions['repositories'] access_check = lambda r: r[1] in ['repository.read', @@ -129,35 +136,35 @@ class RepoModel(BaseModel): users = self.sa.query(User).filter(User.active == True).all() return json.dumps([ { - 'id': u.user_id, - 'fname': u.name, - 'lname': u.lastname, - 'nname': u.username, - 'gravatar_lnk': h.gravatar_url(u.email, 14) + 'id': u.user_id, + 'fname': u.name, + 'lname': u.lastname, + 'nname': u.username, + 'gravatar_lnk': h.gravatar_url(u.email, 14) } for u in users] ) - def get_users_groups_js(self): - users_groups = self.sa.query(UserGroup)\ + def get_user_groups_js(self): + user_groups = self.sa.query(UserGroup) \ .filter(UserGroup.users_group_active == True).all() - users_groups = UserGroupList(users_groups, perm_set=['usergroup.read', - 'usergroup.write', - 'usergroup.admin']) + user_groups = UserGroupList(user_groups, perm_set=['usergroup.read', + 'usergroup.write', + 'usergroup.admin']) return json.dumps([ { - 'id': gr.users_group_id, - 'grname': gr.users_group_name, - 'grmembers': len(gr.members), - } for gr in users_groups] + 'id': gr.users_group_id, + 'grname': gr.users_group_name, + 'grmembers': len(gr.members), + } for gr in user_groups] ) @classmethod def _render_datatable(cls, tmpl, *args, **kwargs): - import rhodecode + import kallithea from pylons import tmpl_context as c from pylons.i18n.translation import _ - _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup + _tmpl_lookup = kallithea.CONFIG['pylons.app_globals'].mako_lookup template = _tmpl_lookup.get_template('data_table/_dt_elements.html') tmpl = template.get_def(tmpl) @@ -179,8 +186,8 @@ class RepoModel(BaseModel): def quick_menu(repo_name): return _render('quick_menu', repo_name) - def repo_lnk(name, rtype, private, fork_of): - return _render('repo_name', name, rtype, private, fork_of, + def repo_lnk(name, rtype, rstate, private, fork_of): + return _render('repo_name', name, rtype, rstate, private, fork_of, short_name=not admin, admin=False) def last_change(last_change): @@ -203,6 +210,9 @@ class RepoModel(BaseModel): else: return h.urlify_text(h.truncate(desc, 60)) + def state(repo_state): + return _render("repo_state", repo_state) + def repo_actions(repo_name): return _render('repo_actions', repo_name, super_user_actions) @@ -214,7 +224,8 @@ class RepoModel(BaseModel): if perm_check: # check permission at this level if not HasRepoPermissionAny( - 'repository.read', 'repository.write', 'repository.admin' + 'repository.read', 'repository.write', + 'repository.admin' )(repo.repo_name, 'get_repos_as_dict check'): continue cs_cache = repo.changeset_cache @@ -222,12 +233,13 @@ class RepoModel(BaseModel): "menu": quick_menu(repo.repo_name), "raw_name": repo.repo_name.lower(), "name": repo_lnk(repo.repo_name, repo.repo_type, - repo.private, repo.fork), + repo.repo_state, repo.private, repo.fork), "last_change": last_change(repo.last_db_change), "last_changeset": last_rev(repo.repo_name, cs_cache), - "raw_tip": cs_cache.get('revision'), + "last_rev_raw": cs_cache.get('revision'), "desc": desc(repo.description), "owner": h.person(repo.user.username), + "state": state(repo.repo_state), "rss": rss_lnk(repo.repo_name), "atom": atom_lnk(repo.repo_name), @@ -268,14 +280,19 @@ class RepoModel(BaseModel): 'group_id', None) for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'), - (1, 'repo_description'), (1, 'repo_enable_locking'), - (1, 'repo_landing_rev'), (0, 'clone_uri'), - (1, 'repo_private'), (1, 'repo_enable_statistics')]: + (1, 'repo_description'), (1, 'repo_enable_locking'), + (1, 'repo_landing_rev'), (0, 'clone_uri'), + (1, 'repo_private'), (1, 'repo_enable_statistics')]: attr = k if strip: attr = remove_prefix(k, 'repo_') - defaults[k] = defaults[attr] + val = defaults[attr] + if k == 'repo_landing_rev': + val = ':'.join(defaults[attr]) + defaults[k] = val + if k == 'clone_uri': + defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden # fill owner if repo_info.user: @@ -288,33 +305,43 @@ class RepoModel(BaseModel): # fill repository users for p in repo_info.repo_to_perm: defaults.update({'u_perm_%s' % p.user.username: - p.permission.permission_name}) + p.permission.permission_name}) # fill repository groups for p in repo_info.users_group_to_perm: defaults.update({'g_perm_%s' % p.users_group.users_group_name: - p.permission.permission_name}) + p.permission.permission_name}) return defaults - def update(self, org_repo_name, **kwargs): + def update(self, repo, **kwargs): try: - cur_repo = self.get_by_repo_name(org_repo_name, cache=False) - + cur_repo = self._get_repo(repo) + org_repo_name = cur_repo.repo_name if 'user' in kwargs: cur_repo.user = User.get_by_username(kwargs['user']) if 'repo_group' in kwargs: cur_repo.group = RepoGroup.get(kwargs['repo_group']) - + log.debug('Updating repo %s with params:%s' % (cur_repo, kwargs)) for strip, k in [(1, 'repo_enable_downloads'), - (1, 'repo_description'), (1, 'repo_enable_locking'), - (1, 'repo_landing_rev'), (0, 'clone_uri'), - (1, 'repo_private'), (1, 'repo_enable_statistics')]: + (1, 'repo_description'), + (1, 'repo_enable_locking'), + (1, 'repo_landing_rev'), + (1, 'repo_private'), + (1, 'repo_enable_statistics'), + (0, 'clone_uri'),]: if k in kwargs: val = kwargs[k] if strip: k = remove_prefix(k, 'repo_') + if k == 'clone_uri': + from kallithea.model.validators import Missing + _change = kwargs.get('clone_uri_change') + if _change == Missing: + # we don't change the value, so use original one + val = cur_repo.clone_uri + setattr(cur_repo, k, val) new_name = cur_repo.get_new_name(kwargs['repo_name']) @@ -326,8 +353,9 @@ class RepoModel(BaseModel): RepoModel().grant_user_permission( repo=cur_repo, user='default', perm=EMPTY_PERM ) - #handle extra fields - for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs): + #handle extra fields + for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), + kwargs): k = RepositoryField.un_prefix_key(field) ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo) if ex_field: @@ -337,29 +365,32 @@ class RepoModel(BaseModel): if org_repo_name != new_name: # rename repository - self.__rename_repo(old=org_repo_name, new=new_name) + self._rename_filesystem_repo(old=org_repo_name, new=new_name) return cur_repo except Exception: log.error(traceback.format_exc()) raise - def create_repo(self, repo_name, repo_type, description, owner, - private=False, clone_uri=None, repos_group=None, - landing_rev='tip', just_db=False, fork_of=None, - copy_fork_permissions=False, enable_statistics=False, - enable_locking=False, enable_downloads=False): + def _create_repo(self, repo_name, repo_type, description, owner, + private=False, clone_uri=None, repo_group=None, + landing_rev='rev:tip', fork_of=None, + copy_fork_permissions=False, enable_statistics=False, + enable_locking=False, enable_downloads=False, + copy_group_permissions=False, state=Repository.STATE_PENDING): """ - Create repository + Create repository inside database with PENDING state, this should be + only executed by create() repo. With exception of importing existing repos """ - from rhodecode.model.scm import ScmModel + from kallithea.model.scm import ScmModel owner = self._get_user(owner) fork_of = self._get_repo(fork_of) - repos_group = self._get_repo_group(repos_group) + repo_group = self._get_repo_group(repo_group) try: - + repo_name = safe_unicode(repo_name) + description = safe_unicode(description) # repo name is just a name of repository # while repo_name_full is a full qualified name that is combined # with name and path of group @@ -367,11 +398,12 @@ class RepoModel(BaseModel): repo_name = repo_name.split(self.URL_SEPARATOR)[-1] new_repo = Repository() + new_repo.repo_state = state new_repo.enable_statistics = False new_repo.repo_name = repo_name_full new_repo.repo_type = repo_type new_repo.user = owner - new_repo.group = repos_group + new_repo.group = repo_group new_repo.description = description or repo_name new_repo.private = private new_repo.clone_uri = clone_uri @@ -381,8 +413,8 @@ class RepoModel(BaseModel): new_repo.enable_locking = enable_locking new_repo.enable_downloads = enable_downloads - if repos_group: - new_repo.enable_locking = repos_group.enable_locking + if repo_group: + new_repo.enable_locking = repo_group.enable_locking if fork_of: parent_repo = fork_of @@ -390,74 +422,62 @@ class RepoModel(BaseModel): self.sa.add(new_repo) - if fork_of: - if copy_fork_permissions: - repo = fork_of - user_perms = UserRepoToPerm.query()\ - .filter(UserRepoToPerm.repository == repo).all() - group_perms = UserGroupRepoToPerm.query()\ - .filter(UserGroupRepoToPerm.repository == repo).all() + if fork_of and copy_fork_permissions: + repo = fork_of + user_perms = UserRepoToPerm.query() \ + .filter(UserRepoToPerm.repository == repo).all() + group_perms = UserGroupRepoToPerm.query() \ + .filter(UserGroupRepoToPerm.repository == repo).all() + + for perm in user_perms: + UserRepoToPerm.create(perm.user, new_repo, perm.permission) + + for perm in group_perms: + UserGroupRepoToPerm.create(perm.users_group, new_repo, + perm.permission) + + elif repo_group and copy_group_permissions: - for perm in user_perms: - UserRepoToPerm.create(perm.user, new_repo, - perm.permission) + user_perms = UserRepoGroupToPerm.query() \ + .filter(UserRepoGroupToPerm.group == repo_group).all() + + group_perms = UserGroupRepoGroupToPerm.query() \ + .filter(UserGroupRepoGroupToPerm.group == repo_group).all() - for perm in group_perms: - UserGroupRepoToPerm.create(perm.users_group, new_repo, - perm.permission) - else: - perm_obj = self._create_default_perms(new_repo, private) - self.sa.add(perm_obj) + for perm in user_perms: + perm_name = perm.permission.permission_name.replace('group.', 'repository.') + perm_obj = Permission.get_by_key(perm_name) + UserRepoToPerm.create(perm.user, new_repo, perm_obj) + + for perm in group_perms: + perm_name = perm.permission.permission_name.replace('group.', 'repository.') + perm_obj = Permission.get_by_key(perm_name) + UserGroupRepoToPerm.create(perm.users_group, new_repo, perm_obj) + else: perm_obj = self._create_default_perms(new_repo, private) self.sa.add(perm_obj) - if not just_db: - self.__create_repo(repo_name, repo_type, - repos_group, - clone_uri) - log_create_repository(new_repo.get_dict(), - created_by=owner.username) - # now automatically start following this repository as owner ScmModel(self.sa).toggle_following_repo(new_repo.repo_id, owner.user_id) + # we need to flush here, in order to check if database won't + # throw any exceptions, create filesystem dirs at the very end + self.sa.flush() return new_repo except Exception: log.error(traceback.format_exc()) raise - def create(self, form_data, cur_user, just_db=False, fork=None): + def create(self, form_data, cur_user): """ - Backward compatibility function, just a wrapper on top of create_repo + Create repository using celery tasks :param form_data: :param cur_user: - :param just_db: - :param fork: """ - owner = cur_user - repo_name = form_data['repo_name_full'] - repo_type = form_data['repo_type'] - description = form_data['repo_description'] - private = form_data['repo_private'] - clone_uri = form_data.get('clone_uri') - repos_group = form_data['repo_group'] - landing_rev = form_data['repo_landing_rev'] - copy_fork_permissions = form_data.get('copy_permissions') - fork_of = form_data.get('fork_parent_id') - - ## repo creation defaults, private and repo_type are filled in form - defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True) - enable_statistics = defs.get('repo_enable_statistics') - enable_locking = defs.get('repo_enable_locking') - enable_downloads = defs.get('repo_enable_downloads') - - return self.create_repo( - repo_name, repo_type, description, owner, private, clone_uri, - repos_group, landing_rev, just_db, fork_of, copy_fork_permissions, - enable_statistics, enable_locking, enable_downloads - ) + from kallithea.lib.celerylib import tasks, run_task + return run_task(tasks.create_repo, form_data, cur_user) def _update_permissions(self, repo, perms_new=None, perms_updates=None, check_perms=True): @@ -475,12 +495,14 @@ class RepoModel(BaseModel): ) else: #check if we have permissions to alter this usergroup - req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin') - if not check_perms or HasUserGroupPermissionAny(*req_perms)(member): - self.grant_users_group_permission( + req_perms = ( + 'usergroup.read', 'usergroup.write', 'usergroup.admin') + if not check_perms or HasUserGroupPermissionAny(*req_perms)( + member): + self.grant_user_group_permission( repo=repo, group_name=member, perm=perm ) - # set new permissions + # set new permissions for member, perm, member_type in perms_new: if member_type == 'user': self.grant_user_permission( @@ -488,9 +510,11 @@ class RepoModel(BaseModel): ) else: #check if we have permissions to alter this usergroup - req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin') - if not check_perms or HasUserGroupPermissionAny(*req_perms)(member): - self.grant_users_group_permission( + req_perms = ( + 'usergroup.read', 'usergroup.write', 'usergroup.admin') + if not check_perms or HasUserGroupPermissionAny(*req_perms)( + member): + self.grant_user_group_permission( repo=repo, group_name=member, perm=perm ) @@ -501,8 +525,8 @@ class RepoModel(BaseModel): :param form_data: :param cur_user: """ - from rhodecode.lib.celerylib import tasks, run_task - run_task(tasks.create_repo_fork, form_data, cur_user) + from kallithea.lib.celerylib import tasks, run_task + return run_task(tasks.create_repo_fork, form_data, cur_user) def delete(self, repo, forks=None, fs_remove=True, cur_user=None): """ @@ -515,7 +539,7 @@ class RepoModel(BaseModel): :param fs_remove: remove(archive) repo from filesystem """ if not cur_user: - cur_user = getattr(get_current_rhodecode_user(), 'username', None) + cur_user = getattr(get_current_authuser(), 'username', None) repo = self._get_repo(repo) if repo: if forks == 'detach': @@ -533,7 +557,7 @@ class RepoModel(BaseModel): try: self.sa.delete(repo) if fs_remove: - self.__delete_repo(repo) + self._delete_filesystem_repo(repo) else: log.debug('skipping removal from filesystem') log_delete_repository(old_repo_dict, @@ -556,9 +580,9 @@ class RepoModel(BaseModel): permission = self._get_perm(perm) # check if we have that permission already - obj = self.sa.query(UserRepoToPerm)\ - .filter(UserRepoToPerm.user == user)\ - .filter(UserRepoToPerm.repository == repo)\ + obj = self.sa.query(UserRepoToPerm) \ + .filter(UserRepoToPerm.user == user) \ + .filter(UserRepoToPerm.repository == repo) \ .scalar() if obj is None: # create new ! @@ -568,6 +592,7 @@ class RepoModel(BaseModel): obj.permission = permission self.sa.add(obj) log.debug('Granted perm %s to %s on %s' % (perm, user, repo)) + return obj def revoke_user_permission(self, repo, user): """ @@ -580,15 +605,15 @@ class RepoModel(BaseModel): user = self._get_user(user) repo = self._get_repo(repo) - obj = self.sa.query(UserRepoToPerm)\ - .filter(UserRepoToPerm.repository == repo)\ - .filter(UserRepoToPerm.user == user)\ + obj = self.sa.query(UserRepoToPerm) \ + .filter(UserRepoToPerm.repository == repo) \ + .filter(UserRepoToPerm.user == user) \ .scalar() if obj: self.sa.delete(obj) log.debug('Revoked perm on %s on %s' % (repo, user)) - def grant_users_group_permission(self, repo, group_name, perm): + def grant_user_group_permission(self, repo, group_name, perm): """ Grant permission for user group on given repository, or update existing one if found @@ -603,9 +628,9 @@ class RepoModel(BaseModel): permission = self._get_perm(perm) # check if we have that permission already - obj = self.sa.query(UserGroupRepoToPerm)\ - .filter(UserGroupRepoToPerm.users_group == group_name)\ - .filter(UserGroupRepoToPerm.repository == repo)\ + obj = self.sa.query(UserGroupRepoToPerm) \ + .filter(UserGroupRepoToPerm.users_group == group_name) \ + .filter(UserGroupRepoToPerm.repository == repo) \ .scalar() if obj is None: @@ -617,8 +642,9 @@ class RepoModel(BaseModel): obj.permission = permission self.sa.add(obj) log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo)) + return obj - def revoke_users_group_permission(self, repo, group_name): + def revoke_user_group_permission(self, repo, group_name): """ Revoke permission for user group on given repository @@ -629,9 +655,9 @@ class RepoModel(BaseModel): repo = self._get_repo(repo) group_name = self._get_user_group(group_name) - obj = self.sa.query(UserGroupRepoToPerm)\ - .filter(UserGroupRepoToPerm.repository == repo)\ - .filter(UserGroupRepoToPerm.users_group == group_name)\ + obj = self.sa.query(UserGroupRepoToPerm) \ + .filter(UserGroupRepoToPerm.repository == repo) \ + .filter(UserGroupRepoToPerm.users_group == group_name) \ .scalar() if obj: self.sa.delete(obj) @@ -645,21 +671,16 @@ class RepoModel(BaseModel): """ repo = self._get_repo(repo_name) try: - obj = self.sa.query(Statistics)\ - .filter(Statistics.repository == repo).scalar() + obj = self.sa.query(Statistics) \ + .filter(Statistics.repository == repo).scalar() if obj: self.sa.delete(obj) except Exception: log.error(traceback.format_exc()) raise - def _create_repo(self, repo_name, alias, parent, clone_uri=False, - repo_store_location=None): - return self.__create_repo(repo_name, alias, parent, clone_uri, - repo_store_location) - - def __create_repo(self, repo_name, alias, parent, clone_uri=False, - repo_store_location=None): + def _create_filesystem_repo(self, repo_name, repo_type, repo_group, + clone_uri=None, repo_store_location=None): """ makes repository on filesystem. It's group aware means it'll create a repository within a group, and alter the paths accordingly of @@ -667,22 +688,26 @@ class RepoModel(BaseModel): :param repo_name: :param alias: - :param parent_id: + :param parent: :param clone_uri: - :param repo_path: + :param repo_store_location: """ - from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group - from rhodecode.model.scm import ScmModel + from kallithea.lib.utils import is_valid_repo, is_valid_repo_group + from kallithea.model.scm import ScmModel + + if '/' in repo_name: + raise ValueError('repo_name must not contain groups got `%s`' % repo_name) - if parent: - new_parent_path = os.sep.join(parent.full_path_splitted) + if isinstance(repo_group, RepoGroup): + new_parent_path = os.sep.join(repo_group.full_path_splitted) else: - new_parent_path = '' + new_parent_path = repo_group or '' + if repo_store_location: _paths = [repo_store_location] else: _paths = [self.repos_path, new_parent_path, repo_name] - # we need to make it str for mercurial + # we need to make it str for mercurial repo_path = os.path.join(*map(lambda x: safe_str(x), _paths)) # check if this path is not a repository @@ -690,26 +715,35 @@ class RepoModel(BaseModel): raise Exception('This path %s is a valid repository' % repo_path) # check if this path is a group - if is_valid_repos_group(repo_path, self.repos_path): + if is_valid_repo_group(repo_path, self.repos_path): raise Exception('This path %s is a valid group' % repo_path) - log.info('creating repo %s in %s @ %s' % ( - repo_name, safe_unicode(repo_path), - obfuscate_url_pw(clone_uri) - ) - ) - backend = get_backend(alias) - if alias == 'hg': - repo = backend(repo_path, create=True, src_url=clone_uri) - elif alias == 'git': + log.info('creating repo %s in %s from url: `%s`' % ( + repo_name, safe_unicode(repo_path), + obfuscate_url_pw(clone_uri))) + + backend = get_backend(repo_type) + + if repo_type == 'hg': + baseui = make_ui('db', clear_session=False) + # patch and reset hooks section of UI config to not run any + # hooks on creating remote repo + for k, v in baseui.configitems('hooks'): + baseui.setconfig('hooks', k, None) + + repo = backend(repo_path, create=True, src_url=clone_uri, baseui=baseui) + elif repo_type == 'git': repo = backend(repo_path, create=True, src_url=clone_uri, bare=True) - # add rhodecode hook into this repo + # add kallithea hook into this repo ScmModel().install_git_hook(repo=repo) else: - raise Exception('Undefined alias %s' % alias) + raise Exception('Not supported repo_type %s expected hg/git' % repo_type) + + log.debug('Created repo %s with %s backend' + % (safe_unicode(repo_name), safe_unicode(repo_type))) return repo - def __rename_repo(self, old, new): + def _rename_filesystem_repo(self, old, new): """ renames repository on filesystem @@ -726,27 +760,29 @@ class RepoModel(BaseModel): ) shutil.move(old_path, new_path) - def __delete_repo(self, repo): + def _delete_filesystem_repo(self, repo): """ removes repo from filesystem, the removal is acctually made by added rm__ prefix into dir, and rename internat .hg/.git dirs so this - repository is no longer valid for rhodecode, can be undeleted later on + repository is no longer valid for kallithea, can be undeleted later on by reverting the renames on this repository :param repo: repo object """ rm_path = os.path.join(self.repos_path, repo.repo_name) - log.info("Removing %s" % (rm_path)) + log.info("Removing repository %s" % (rm_path,)) # disable hg/git internal that it doesn't get detected as repo alias = repo.repo_type bare = getattr(repo.scm_instance, 'bare', False) + # skip this for bare git repos if not bare: - # skip this for bare git repos - shutil.move(os.path.join(rm_path, '.%s' % alias), - os.path.join(rm_path, 'rm__.%s' % alias)) - # disable repo + # disable VCS repo + vcs_path = os.path.join(rm_path, '.%s' % alias) + if os.path.exists(vcs_path): + shutil.move(vcs_path, os.path.join(rm_path, 'rm__.%s' % alias)) + _now = datetime.now() _ms = str(_now.microsecond).rjust(6, '0') _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms), @@ -754,4 +790,6 @@ class RepoModel(BaseModel): if repo.group: args = repo.group.full_path_splitted + [_d] _d = os.path.join(*args) - shutil.move(rm_path, os.path.join(self.repos_path, _d)) + + if os.path.isdir(rm_path): + shutil.move(rm_path, os.path.join(self.repos_path, _d)) diff --git a/kallithea/model/repo_group.py b/kallithea/model/repo_group.py new file mode 100644 --- /dev/null +++ b/kallithea/model/repo_group.py @@ -0,0 +1,542 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.user_group +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +repo group model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Jan 25, 2011 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + + +import os +import logging +import traceback +import shutil +import datetime + +from kallithea.lib.utils2 import LazyProperty + +from kallithea.model import BaseModel +from kallithea.model.db import RepoGroup, Ui, UserRepoGroupToPerm, \ + User, Permission, UserGroupRepoGroupToPerm, UserGroup, Repository + +log = logging.getLogger(__name__) + + +class RepoGroupModel(BaseModel): + + cls = RepoGroup + + def _get_user_group(self, users_group): + return self._get_instance(UserGroup, users_group, + callback=UserGroup.get_by_group_name) + + def _get_repo_group(self, repo_group): + return self._get_instance(RepoGroup, repo_group, + callback=RepoGroup.get_by_group_name) + + @LazyProperty + def repos_path(self): + """ + Gets the repositories root path from database + """ + + q = Ui.get_by_key('/') + return q.ui_value + + def _create_default_perms(self, new_group): + # create default permission + default_perm = 'group.read' + def_user = User.get_default_user() + for p in def_user.user_perms: + if p.permission.permission_name.startswith('group.'): + default_perm = p.permission.permission_name + break + + repo_group_to_perm = UserRepoGroupToPerm() + repo_group_to_perm.permission = Permission.get_by_key(default_perm) + + repo_group_to_perm.group = new_group + repo_group_to_perm.user_id = def_user.user_id + return repo_group_to_perm + + def _create_group(self, group_name): + """ + makes repository group on filesystem + + :param repo_name: + :param parent_id: + """ + + create_path = os.path.join(self.repos_path, group_name) + log.debug('creating new group in %s' % create_path) + + if os.path.isdir(create_path): + raise Exception('That directory already exists !') + + os.makedirs(create_path) + log.debug('Created group in %s' % create_path) + + def _rename_group(self, old, new): + """ + Renames a group on filesystem + + :param group_name: + """ + + if old == new: + log.debug('skipping group rename') + return + + log.debug('renaming repository group from %s to %s' % (old, new)) + + old_path = os.path.join(self.repos_path, old) + new_path = os.path.join(self.repos_path, new) + + log.debug('renaming repos paths from %s to %s' % (old_path, new_path)) + + if os.path.isdir(new_path): + raise Exception('Was trying to rename to already ' + 'existing dir %s' % new_path) + shutil.move(old_path, new_path) + + def _delete_group(self, group, force_delete=False): + """ + Deletes a group from a filesystem + + :param group: instance of group from database + :param force_delete: use shutil rmtree to remove all objects + """ + paths = group.full_path.split(RepoGroup.url_sep()) + paths = os.sep.join(paths) + + rm_path = os.path.join(self.repos_path, paths) + log.info("Removing group %s" % (rm_path)) + # delete only if that path really exists + if os.path.isdir(rm_path): + if force_delete: + shutil.rmtree(rm_path) + else: + #archive that group` + _now = datetime.datetime.now() + _ms = str(_now.microsecond).rjust(6, '0') + _d = 'rm__%s_GROUP_%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms), + group.name) + shutil.move(rm_path, os.path.join(self.repos_path, _d)) + + def create(self, group_name, group_description, owner, parent=None, + just_db=False, copy_permissions=False): + try: + user = self._get_user(owner) + parent_group = self._get_repo_group(parent) + new_repo_group = RepoGroup() + new_repo_group.user = user + new_repo_group.group_description = group_description or group_name + new_repo_group.parent_group = parent_group + new_repo_group.group_name = new_repo_group.get_new_name(group_name) + + self.sa.add(new_repo_group) + + # create an ADMIN permission for owner except if we're super admin, + # later owner should go into the owner field of groups + if not user.is_admin: + self.grant_user_permission(repo_group=new_repo_group, + user=owner, perm='group.admin') + + if parent_group and copy_permissions: + # copy permissions from parent + user_perms = UserRepoGroupToPerm.query() \ + .filter(UserRepoGroupToPerm.group == parent_group).all() + + group_perms = UserGroupRepoGroupToPerm.query() \ + .filter(UserGroupRepoGroupToPerm.group == parent_group).all() + + for perm in user_perms: + # don't copy over the permission for user who is creating + # this group, if he is not super admin he get's admin + # permission set above + if perm.user != user or user.is_admin: + UserRepoGroupToPerm.create(perm.user, new_repo_group, perm.permission) + + for perm in group_perms: + UserGroupRepoGroupToPerm.create(perm.users_group, new_repo_group, perm.permission) + else: + perm_obj = self._create_default_perms(new_repo_group) + self.sa.add(perm_obj) + + if not just_db: + # we need to flush here, in order to check if database won't + # throw any exceptions, create filesystem dirs at the very end + self.sa.flush() + self._create_group(new_repo_group.group_name) + + return new_repo_group + except Exception: + log.error(traceback.format_exc()) + raise + + def _update_permissions(self, repo_group, perms_new=None, + perms_updates=None, recursive=None, + check_perms=True): + from kallithea.model.repo import RepoModel + from kallithea.lib.auth import HasUserGroupPermissionAny + + if not perms_new: + perms_new = [] + if not perms_updates: + perms_updates = [] + + def _set_perm_user(obj, user, perm): + if isinstance(obj, RepoGroup): + self.grant_user_permission(repo_group=obj, user=user, perm=perm) + elif isinstance(obj, Repository): + # private repos will not allow to change the default permissions + # using recursive mode + if obj.private and user == User.DEFAULT_USER: + return + + # we set group permission but we have to switch to repo + # permission + perm = perm.replace('group.', 'repository.') + RepoModel().grant_user_permission( + repo=obj, user=user, perm=perm + ) + + def _set_perm_group(obj, users_group, perm): + if isinstance(obj, RepoGroup): + self.grant_user_group_permission(repo_group=obj, + group_name=users_group, + perm=perm) + elif isinstance(obj, Repository): + # we set group permission but we have to switch to repo + # permission + perm = perm.replace('group.', 'repository.') + RepoModel().grant_user_group_permission( + repo=obj, group_name=users_group, perm=perm + ) + + # start updates + updates = [] + log.debug('Now updating permissions for %s in recursive mode:%s' + % (repo_group, recursive)) + + for obj in repo_group.recursive_groups_and_repos(): + # iterated obj is an instance of a repos group or repository in + # that group, recursive option can be: none, repos, groups, all + if recursive == 'all': + obj = obj + elif recursive == 'repos': + # skip groups, other than this one + if isinstance(obj, RepoGroup) and not obj == repo_group: + continue + elif recursive == 'groups': + # skip repos + if isinstance(obj, Repository): + continue + else: # recursive == 'none': # DEFAULT don't apply to iterated objects + obj = repo_group + # also we do a break at the end of this loop. + + # update permissions + for member, perm, member_type in perms_updates: + ## set for user + if member_type == 'user': + # this updates also current one if found + _set_perm_user(obj, user=member, perm=perm) + ## set for user group + else: + #check if we have permissions to alter this usergroup + req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin') + if not check_perms or HasUserGroupPermissionAny(*req_perms)(member): + _set_perm_group(obj, users_group=member, perm=perm) + # set new permissions + for member, perm, member_type in perms_new: + if member_type == 'user': + _set_perm_user(obj, user=member, perm=perm) + else: + #check if we have permissions to alter this usergroup + req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin') + if not check_perms or HasUserGroupPermissionAny(*req_perms)(member): + _set_perm_group(obj, users_group=member, perm=perm) + updates.append(obj) + # if it's not recursive call for all,repos,groups + # break the loop and don't proceed with other changes + if recursive not in ['all', 'repos', 'groups']: + break + + return updates + + def update(self, repo_group, form_data): + + try: + repo_group = self._get_repo_group(repo_group) + old_path = repo_group.full_path + + # change properties + repo_group.group_description = form_data['group_description'] + repo_group.group_parent_id = form_data['group_parent_id'] + repo_group.enable_locking = form_data['enable_locking'] + + repo_group.parent_group = RepoGroup.get(form_data['group_parent_id']) + repo_group.group_name = repo_group.get_new_name(form_data['group_name']) + new_path = repo_group.full_path + self.sa.add(repo_group) + + # iterate over all members of this groups and do fixes + # set locking if given + # if obj is a repoGroup also fix the name of the group according + # to the parent + # if obj is a Repo fix it's name + # this can be potentially heavy operation + for obj in repo_group.recursive_groups_and_repos(): + #set the value from it's parent + obj.enable_locking = repo_group.enable_locking + if isinstance(obj, RepoGroup): + new_name = obj.get_new_name(obj.name) + log.debug('Fixing group %s to new name %s' \ + % (obj.group_name, new_name)) + obj.group_name = new_name + elif isinstance(obj, Repository): + # we need to get all repositories from this new group and + # rename them accordingly to new group path + new_name = obj.get_new_name(obj.just_name) + log.debug('Fixing repo %s to new name %s' \ + % (obj.repo_name, new_name)) + obj.repo_name = new_name + self.sa.add(obj) + + self._rename_group(old_path, new_path) + + return repo_group + except Exception: + log.error(traceback.format_exc()) + raise + + def delete(self, repo_group, force_delete=False): + repo_group = self._get_repo_group(repo_group) + try: + self.sa.delete(repo_group) + self._delete_group(repo_group, force_delete) + except Exception: + log.error('Error removing repo_group %s' % repo_group) + raise + + def add_permission(self, repo_group, obj, obj_type, perm, recursive): + from kallithea.model.repo import RepoModel + repo_group = self._get_repo_group(repo_group) + perm = self._get_perm(perm) + + for el in repo_group.recursive_groups_and_repos(): + # iterated obj is an instance of a repos group or repository in + # that group, recursive option can be: none, repos, groups, all + if recursive == 'all': + el = el + elif recursive == 'repos': + # skip groups, other than this one + if isinstance(el, RepoGroup) and not el == repo_group: + continue + elif recursive == 'groups': + # skip repos + if isinstance(el, Repository): + continue + else: # recursive == 'none': # DEFAULT don't apply to iterated objects + el = repo_group + # also we do a break at the end of this loop. + + if isinstance(el, RepoGroup): + if obj_type == 'user': + RepoGroupModel().grant_user_permission(el, user=obj, perm=perm) + elif obj_type == 'user_group': + RepoGroupModel().grant_user_group_permission(el, group_name=obj, perm=perm) + else: + raise Exception('undefined object type %s' % obj_type) + elif isinstance(el, Repository): + # for repos we need to hotfix the name of permission + _perm = perm.permission_name.replace('group.', 'repository.') + if obj_type == 'user': + RepoModel().grant_user_permission(el, user=obj, perm=_perm) + elif obj_type == 'user_group': + RepoModel().grant_user_group_permission(el, group_name=obj, perm=_perm) + else: + raise Exception('undefined object type %s' % obj_type) + else: + raise Exception('el should be instance of Repository or ' + 'RepositoryGroup got %s instead' % type(el)) + + # if it's not recursive call for all,repos,groups + # break the loop and don't proceed with other changes + if recursive not in ['all', 'repos', 'groups']: + break + + def delete_permission(self, repo_group, obj, obj_type, recursive): + """ + Revokes permission for repo_group for given obj(user or users_group), + obj_type can be user or user group + + :param repo_group: + :param obj: user or user group id + :param obj_type: user or user group type + :param recursive: recurse to all children of group + """ + from kallithea.model.repo import RepoModel + repo_group = self._get_repo_group(repo_group) + + for el in repo_group.recursive_groups_and_repos(): + # iterated obj is an instance of a repos group or repository in + # that group, recursive option can be: none, repos, groups, all + if recursive == 'all': + el = el + elif recursive == 'repos': + # skip groups, other than this one + if isinstance(el, RepoGroup) and not el == repo_group: + continue + elif recursive == 'groups': + # skip repos + if isinstance(el, Repository): + continue + else: # recursive == 'none': # DEFAULT don't apply to iterated objects + el = repo_group + # also we do a break at the end of this loop. + + if isinstance(el, RepoGroup): + if obj_type == 'user': + RepoGroupModel().revoke_user_permission(el, user=obj) + elif obj_type == 'user_group': + RepoGroupModel().revoke_user_group_permission(el, group_name=obj) + else: + raise Exception('undefined object type %s' % obj_type) + elif isinstance(el, Repository): + if obj_type == 'user': + RepoModel().revoke_user_permission(el, user=obj) + elif obj_type == 'user_group': + RepoModel().revoke_user_group_permission(el, group_name=obj) + else: + raise Exception('undefined object type %s' % obj_type) + else: + raise Exception('el should be instance of Repository or ' + 'RepositoryGroup got %s instead' % type(el)) + + # if it's not recursive call for all,repos,groups + # break the loop and don't proceed with other changes + if recursive not in ['all', 'repos', 'groups']: + break + + def grant_user_permission(self, repo_group, user, perm): + """ + Grant permission for user on given repository group, or update + existing one if found + + :param repo_group: Instance of RepoGroup, repositories_group_id, + or repositories_group name + :param user: Instance of User, user_id or username + :param perm: Instance of Permission, or permission_name + """ + + repo_group = self._get_repo_group(repo_group) + user = self._get_user(user) + permission = self._get_perm(perm) + + # check if we have that permission already + obj = self.sa.query(UserRepoGroupToPerm)\ + .filter(UserRepoGroupToPerm.user == user)\ + .filter(UserRepoGroupToPerm.group == repo_group)\ + .scalar() + if obj is None: + # create new ! + obj = UserRepoGroupToPerm() + obj.group = repo_group + obj.user = user + obj.permission = permission + self.sa.add(obj) + log.debug('Granted perm %s to %s on %s' % (perm, user, repo_group)) + return obj + + def revoke_user_permission(self, repo_group, user): + """ + Revoke permission for user on given repository group + + :param repo_group: Instance of RepoGroup, repositories_group_id, + or repositories_group name + :param user: Instance of User, user_id or username + """ + + repo_group = self._get_repo_group(repo_group) + user = self._get_user(user) + + obj = self.sa.query(UserRepoGroupToPerm)\ + .filter(UserRepoGroupToPerm.user == user)\ + .filter(UserRepoGroupToPerm.group == repo_group)\ + .scalar() + if obj: + self.sa.delete(obj) + log.debug('Revoked perm on %s on %s' % (repo_group, user)) + + def grant_user_group_permission(self, repo_group, group_name, perm): + """ + Grant permission for user group on given repository group, or update + existing one if found + + :param repo_group: Instance of RepoGroup, repositories_group_id, + or repositories_group name + :param group_name: Instance of UserGroup, users_group_id, + or user group name + :param perm: Instance of Permission, or permission_name + """ + repo_group = self._get_repo_group(repo_group) + group_name = self._get_user_group(group_name) + permission = self._get_perm(perm) + + # check if we have that permission already + obj = self.sa.query(UserGroupRepoGroupToPerm)\ + .filter(UserGroupRepoGroupToPerm.group == repo_group)\ + .filter(UserGroupRepoGroupToPerm.users_group == group_name)\ + .scalar() + + if obj is None: + # create new + obj = UserGroupRepoGroupToPerm() + + obj.group = repo_group + obj.users_group = group_name + obj.permission = permission + self.sa.add(obj) + log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo_group)) + return obj + + def revoke_user_group_permission(self, repo_group, group_name): + """ + Revoke permission for user group on given repository group + + :param repo_group: Instance of RepoGroup, repositories_group_id, + or repositories_group name + :param group_name: Instance of UserGroup, users_group_id, + or user group name + """ + repo_group = self._get_repo_group(repo_group) + group_name = self._get_user_group(group_name) + + obj = self.sa.query(UserGroupRepoGroupToPerm)\ + .filter(UserGroupRepoGroupToPerm.group == repo_group)\ + .filter(UserGroupRepoGroupToPerm.users_group == group_name)\ + .scalar() + if obj: + self.sa.delete(obj) + log.debug('Revoked perm to %s on %s' % (repo_group, group_name)) diff --git a/rhodecode/model/repo_permission.py b/kallithea/model/repo_permission.py rename from rhodecode/model/repo_permission.py rename to kallithea/model/repo_permission.py --- a/rhodecode/model/repo_permission.py +++ b/kallithea/model/repo_permission.py @@ -1,16 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.users_group - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - repository permission model for RhodeCode - - :created_on: Oct 1, 2011 - :author: nvinot, marcink - :copyright: (C) 2011-2011 Nicolas Vinot - :copyright: (C) 2011-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -23,10 +11,21 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.users_group +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +repository permission model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Oct 1, 2011 +:author: nvinot, marcink +""" import logging -from rhodecode.model import BaseModel -from rhodecode.model.db import UserRepoToPerm, UserGroupRepoToPerm, \ +from kallithea.model import BaseModel +from kallithea.model.db import UserRepoToPerm, UserGroupRepoToPerm, \ Permission log = logging.getLogger(__name__) diff --git a/rhodecode/model/scm.py b/kallithea/model/scm.py rename from rhodecode/model/scm.py rename to kallithea/model/scm.py --- a/rhodecode/model/scm.py +++ b/kallithea/model/scm.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.scm - ~~~~~~~~~~~~~~~~~~~ - - Scm model for RhodeCode - - :created_on: Apr 9, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,6 +11,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.scm +~~~~~~~~~~~~~~~~~~~ + +Scm model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 9, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + from __future__ import with_statement import os import re @@ -35,26 +38,26 @@ from os.path import join as jn from sqlalchemy import func from pylons.i18n.translation import _ -import rhodecode -from rhodecode.lib.vcs import get_backend -from rhodecode.lib.vcs.exceptions import RepositoryError -from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.nodes import FileNode -from rhodecode.lib.vcs.backends.base import EmptyChangeset +import kallithea +from kallithea.lib.vcs import get_backend +from kallithea.lib.vcs.exceptions import RepositoryError +from kallithea.lib.vcs.utils.lazy import LazyProperty +from kallithea.lib.vcs.nodes import FileNode +from kallithea.lib.vcs.backends.base import EmptyChangeset -from rhodecode import BACKENDS -from rhodecode.lib import helpers as h -from rhodecode.lib.utils2 import safe_str, safe_unicode, get_server_url,\ +from kallithea import BACKENDS +from kallithea.lib import helpers as h +from kallithea.lib.utils2 import safe_str, safe_unicode, get_server_url,\ _set_extras -from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny,\ +from kallithea.lib.auth import HasRepoPermissionAny, HasRepoGroupPermissionAny,\ HasUserGroupPermissionAny -from rhodecode.lib.utils import get_filesystem_repos, make_ui, \ +from kallithea.lib.utils import get_filesystem_repos, make_ui, \ action_logger -from rhodecode.model import BaseModel -from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \ +from kallithea.model import BaseModel +from kallithea.model.db import Repository, Ui, CacheInvalidation, \ UserFollowing, UserLog, User, RepoGroup, PullRequest -from rhodecode.lib.hooks import log_push_action -from rhodecode.lib.exceptions import NonRelativePathError, IMCCommitError +from kallithea.lib.hooks import log_push_action +from kallithea.lib.exceptions import NonRelativePathError, IMCCommitError log = logging.getLogger(__name__) @@ -154,19 +157,16 @@ class SimpleCachedRepoList(CachedRepoLis *self.perm_set)(dbr.repo_name, 'get repo check'): continue - tmp_d = {} - tmp_d['name'] = dbr.repo_name - tmp_d['name_sort'] = tmp_d['name'].lower() - tmp_d['raw_name'] = tmp_d['name'].lower() - tmp_d['description'] = dbr.description - tmp_d['description_sort'] = tmp_d['description'].lower() - tmp_d['dbrepo'] = dbr.get_dict() - tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {} + tmp_d = { + 'name': dbr.repo_name, + 'dbrepo': dbr.get_dict(), + 'dbrepo_fork': dbr.fork.get_dict() if dbr.fork else {} + } yield tmp_d class _PermCheckIterator(object): - def __init__(self, obj_list, obj_attr, perm_set, perm_checker): + def __init__(self, obj_list, obj_attr, perm_set, perm_checker, extra_kwargs=None): """ Creates iterator from given list of objects, additionally checking permission for them from perm_set var @@ -180,6 +180,7 @@ class _PermCheckIterator(object): self.obj_attr = obj_attr self.perm_set = perm_set self.perm_checker = perm_checker + self.extra_kwargs = extra_kwargs or {} def __len__(self): return len(self.obj_list) @@ -191,7 +192,8 @@ class _PermCheckIterator(object): for db_obj in self.obj_list: # check permission at this level name = getattr(db_obj, self.obj_attr, None) - if not self.perm_checker(*self.perm_set)(name, self.__class__.__name__): + if not self.perm_checker(*self.perm_set)( + name, self.__class__.__name__, **self.extra_kwargs): continue yield db_obj @@ -199,35 +201,38 @@ class _PermCheckIterator(object): class RepoList(_PermCheckIterator): - def __init__(self, db_repo_list, perm_set=None): + def __init__(self, db_repo_list, perm_set=None, extra_kwargs=None): if not perm_set: perm_set = ['repository.read', 'repository.write', 'repository.admin'] super(RepoList, self).__init__(obj_list=db_repo_list, obj_attr='repo_name', perm_set=perm_set, - perm_checker=HasRepoPermissionAny) + perm_checker=HasRepoPermissionAny, + extra_kwargs=extra_kwargs) class RepoGroupList(_PermCheckIterator): - def __init__(self, db_repo_group_list, perm_set=None): + def __init__(self, db_repo_group_list, perm_set=None, extra_kwargs=None): if not perm_set: perm_set = ['group.read', 'group.write', 'group.admin'] super(RepoGroupList, self).__init__(obj_list=db_repo_group_list, obj_attr='group_name', perm_set=perm_set, - perm_checker=HasReposGroupPermissionAny) + perm_checker=HasRepoGroupPermissionAny, + extra_kwargs=extra_kwargs) class UserGroupList(_PermCheckIterator): - def __init__(self, db_user_group_list, perm_set=None): + def __init__(self, db_user_group_list, perm_set=None, extra_kwargs=None): if not perm_set: perm_set = ['usergroup.read', 'usergroup.write', 'usergroup.admin'] super(UserGroupList, self).__init__(obj_list=db_user_group_list, obj_attr='users_group_name', perm_set=perm_set, - perm_checker=HasUserGroupPermissionAny) + perm_checker=HasUserGroupPermissionAny, + extra_kwargs=extra_kwargs) class ScmModel(BaseModel): @@ -253,7 +258,7 @@ class ScmModel(BaseModel): Gets the repositories root path from database """ - q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one() + q = self.sa.query(Ui).filter(Ui.ui_key == '/').one() return q.ui_value @@ -275,7 +280,7 @@ class ScmModel(BaseModel): for name, path in get_filesystem_repos(repos_path, recursive=True): # name need to be decomposed and put back together using the / - # since this is internal storage separator for rhodecode + # since this is internal storage separator for kallithea name = Repository.normalize_repo_name(name) try: @@ -322,19 +327,19 @@ class ScmModel(BaseModel): return repo_iter - def get_repos_groups(self, all_groups=None): + def get_repo_groups(self, all_groups=None): if all_groups is None: all_groups = RepoGroup.query()\ .filter(RepoGroup.group_parent_id == None).all() return [x for x in RepoGroupList(all_groups)] - def mark_for_invalidation(self, repo_name): + def mark_for_invalidation(self, repo_name, delete=False): """ Mark caches of this repo invalid in the database. :param repo_name: the repo for which caches should be marked invalid """ - CacheInvalidation.set_invalidate(repo_name) + CacheInvalidation.set_invalidate(repo_name, delete=delete) repo = Repository.get_by_repo_name(repo_name) if repo: repo.update_changeset_cache() @@ -432,14 +437,18 @@ class ScmModel(BaseModel): fork = self.__get_repo(fork) if fork and repo.repo_id == fork.repo_id: raise Exception("Cannot set repository as fork of itself") + + if fork and repo.repo_type != fork.repo_type: + raise RepositoryError("Cannot set repository as fork of repository with other type") + repo.fork = fork self.sa.add(repo) return repo def _handle_rc_scm_extras(self, username, repo_name, repo_alias, action=None): - from rhodecode import CONFIG - from rhodecode.lib.base import _get_ip_addr + from kallithea import CONFIG + from kallithea.lib.base import _get_ip_addr try: from pylons import request environ = request.environ @@ -486,11 +495,11 @@ class ScmModel(BaseModel): :param scm_type: """ if scm_type == 'hg': - from rhodecode.lib.vcs.backends.hg import MercurialInMemoryChangeset + from kallithea.lib.vcs.backends.hg import MercurialInMemoryChangeset return MercurialInMemoryChangeset if scm_type == 'git': - from rhodecode.lib.vcs.backends.git import GitInMemoryChangeset + from kallithea.lib.vcs.backends.git import GitInMemoryChangeset return GitInMemoryChangeset raise Exception('Invalid scm_type, must be one of hg,git got %s' @@ -562,13 +571,50 @@ class ScmModel(BaseModel): revisions=[tip.raw_id]) return tip + def _sanitize_path(self, f_path): + if f_path.startswith('/') or f_path.startswith('.') or '../' in f_path: + raise NonRelativePathError('%s is not an relative path' % f_path) + if f_path: + f_path = os.path.normpath(f_path) + return f_path + + def get_nodes(self, repo_name, revision, root_path='/', flat=True): + """ + recursive walk in root dir and return a set of all path in that dir + based on repository walk function + + :param repo_name: name of repository + :param revision: revision for which to list nodes + :param root_path: root path to list + :param flat: return as a list, if False returns a dict with decription + + """ + _files = list() + _dirs = list() + try: + _repo = self.__get_repo(repo_name) + changeset = _repo.scm_instance.get_changeset(revision) + root_path = root_path.lstrip('/') + for topnode, dirs, files in changeset.walk(root_path): + for f in files: + _files.append(f.path if flat else {"name": f.path, + "type": "file"}) + for d in dirs: + _dirs.append(d.path if flat else {"name": d.path, + "type": "dir"}) + except RepositoryError: + log.debug(traceback.format_exc()) + raise + + return _dirs, _files + def create_nodes(self, user, repo, message, nodes, parent_cs=None, author=None, trigger_push_hook=True): """ Commits given multiple nodes into repo - :param user: RhodeCode User object or user_id, the commiter - :param repo: RhodeCode Repository object + :param user: Kallithea User object or user_id, the commiter + :param repo: Kallithea Repository object :param message: commit message :param nodes: mapping {filename:{'content':content},...} :param parent_cs: parent changeset, can be empty than it's initial commit @@ -583,10 +629,7 @@ class ScmModel(BaseModel): processed_nodes = [] for f_path in nodes: - if f_path.startswith('/') or f_path.startswith('.') or '../' in f_path: - raise NonRelativePathError('%s is not an relative path' % f_path) - if f_path: - f_path = os.path.normpath(f_path) + f_path = self._sanitize_path(f_path) content = nodes[f_path]['content'] f_path = safe_str(f_path) # decoding here will force that we have proper encoded values @@ -634,35 +677,121 @@ class ScmModel(BaseModel): revisions=[tip.raw_id]) return tip - def get_nodes(self, repo_name, revision, root_path='/', flat=True): - """ - recursive walk in root dir and return a set of all path in that dir - based on repository walk function + def update_nodes(self, user, repo, message, nodes, parent_cs=None, + author=None, trigger_push_hook=True): + user = self._get_user(user) + scm_instance = repo.scm_instance_no_cache() + + message = safe_unicode(message) + commiter = user.full_contact + author = safe_unicode(author) if author else commiter + + imc_class = self._get_IMC_module(scm_instance.alias) + imc = imc_class(scm_instance) + + if not parent_cs: + parent_cs = EmptyChangeset(alias=scm_instance.alias) + + if isinstance(parent_cs, EmptyChangeset): + # EmptyChangeset means we we're editing empty repository + parents = None + else: + parents = [parent_cs] + + # add multiple nodes + for _filename, data in nodes.items(): + # new filename, can be renamed from the old one + filename = self._sanitize_path(data['filename']) + old_filename = self._sanitize_path(_filename) + content = data['content'] - :param repo_name: name of repository - :param revision: revision for which to list nodes - :param root_path: root path to list - :param flat: return as a list, if False returns a dict with decription + filenode = FileNode(old_filename, content=content) + op = data['op'] + if op == 'add': + imc.add(filenode) + elif op == 'del': + imc.remove(filenode) + elif op == 'mod': + if filename != old_filename: + #TODO: handle renames, needs vcs lib changes + imc.remove(filenode) + imc.add(FileNode(filename, content=content)) + else: + imc.change(filenode) + # commit changes + tip = imc.commit(message=message, + author=author, + parents=parents, + branch=parent_cs.branch) + + self.mark_for_invalidation(repo.repo_name) + if trigger_push_hook: + self._handle_push(scm_instance, + username=user.username, + action='push_local', + repo_name=repo.repo_name, + revisions=[tip.raw_id]) + + def delete_nodes(self, user, repo, message, nodes, parent_cs=None, + author=None, trigger_push_hook=True): """ - _files = list() - _dirs = list() - try: - _repo = self.__get_repo(repo_name) - changeset = _repo.scm_instance.get_changeset(revision) - root_path = root_path.lstrip('/') - for topnode, dirs, files in changeset.walk(root_path): - for f in files: - _files.append(f.path if flat else {"name": f.path, - "type": "file"}) - for d in dirs: - _dirs.append(d.path if flat else {"name": d.path, - "type": "dir"}) - except RepositoryError: - log.debug(traceback.format_exc()) - raise + Deletes given multiple nodes into repo + + :param user: Kallithea User object or user_id, the commiter + :param repo: Kallithea Repository object + :param message: commit message + :param nodes: mapping {filename:{'content':content},...} + :param parent_cs: parent changeset, can be empty than it's initial commit + :param author: author of commit, cna be different that commiter only for git + :param trigger_push_hook: trigger push hooks + + :returns: new commited changeset after deletion + """ + + user = self._get_user(user) + scm_instance = repo.scm_instance_no_cache() + + processed_nodes = [] + for f_path in nodes: + f_path = self._sanitize_path(f_path) + # content can be empty but for compatabilty it allows same dicts + # structure as add_nodes + content = nodes[f_path].get('content') + processed_nodes.append((f_path, content)) + + message = safe_unicode(message) + commiter = user.full_contact + author = safe_unicode(author) if author else commiter - return _dirs, _files + IMC = self._get_IMC_module(scm_instance.alias) + imc = IMC(scm_instance) + + if not parent_cs: + parent_cs = EmptyChangeset(alias=scm_instance.alias) + + if isinstance(parent_cs, EmptyChangeset): + # EmptyChangeset means we we're editing empty repository + parents = None + else: + parents = [parent_cs] + # add multiple nodes + for path, content in processed_nodes: + imc.remove(FileNode(path, content=content)) + + tip = imc.commit(message=message, + author=author, + parents=parents, + branch=parent_cs.branch) + + self.mark_for_invalidation(repo.repo_name) + if trigger_push_hook: + self._handle_push(scm_instance, + username=user.username, + action='push_local', + repo_name=repo.repo_name, + revisions=[tip.raw_id]) + return tip def get_unread_journal(self): return self.sa.query(UserLog).count() @@ -678,25 +807,25 @@ class ScmModel(BaseModel): hist_l = [] choices = [] repo = self.__get_repo(repo) - hist_l.append(['tip', _('latest tip')]) - choices.append('tip') + hist_l.append(['rev:tip', _('latest tip')]) + choices.append('rev:tip') if not repo: return choices, hist_l repo = repo.scm_instance - branches_group = ([(k, k) for k, v in + branches_group = ([(u'branch:%s' % k, k) for k, v in repo.branches.iteritems()], _("Branches")) hist_l.append(branches_group) choices.extend([x[0] for x in branches_group[0]]) if repo.alias == 'hg': - bookmarks_group = ([(k, k) for k, v in + bookmarks_group = ([(u'book:%s' % k, k) for k, v in repo.bookmarks.iteritems()], _("Bookmarks")) hist_l.append(bookmarks_group) choices.extend([x[0] for x in bookmarks_group[0]]) - tags_group = ([(k, k) for k, v in + tags_group = ([(u'tag:%s' % k, k) for k, v in repo.tags.iteritems()], _("Tags")) hist_l.append(tags_group) choices.extend([x[0] for x in tags_group[0]]) @@ -705,7 +834,7 @@ class ScmModel(BaseModel): def install_git_hook(self, repo, force_create=False): """ - Creates a rhodecode hook inside a git repository + Creates a kallithea hook inside a git repository :param repo: Instance of VCS repo :param force_create: Create even if same name hook exists @@ -718,39 +847,39 @@ class ScmModel(BaseModel): os.makedirs(loc) tmpl_post = pkg_resources.resource_string( - 'rhodecode', jn('config', 'post_receive_tmpl.py') + 'kallithea', jn('config', 'post_receive_tmpl.py') ) tmpl_pre = pkg_resources.resource_string( - 'rhodecode', jn('config', 'pre_receive_tmpl.py') + 'kallithea', jn('config', 'pre_receive_tmpl.py') ) for h_type, tmpl in [('pre', tmpl_pre), ('post', tmpl_post)]: _hook_file = jn(loc, '%s-receive' % h_type) - _rhodecode_hook = False + has_hook = False log.debug('Installing git hook in repo %s' % repo) if os.path.exists(_hook_file): - # let's take a look at this hook, maybe it's rhodecode ? - log.debug('hook exists, checking if it is from rhodecode') + # let's take a look at this hook, maybe it's kallithea ? + log.debug('hook exists, checking if it is from kallithea') with open(_hook_file, 'rb') as f: data = f.read() matches = re.compile(r'(?:%s)\s*=\s*(.*)' - % 'RC_HOOK_VER').search(data) + % 'KALLITHEA_HOOK_VER').search(data) if matches: try: ver = matches.groups()[0] - log.debug('got %s it is rhodecode' % (ver)) - _rhodecode_hook = True + log.debug('got %s it is kallithea' % (ver)) + has_hook = True except Exception: log.error(traceback.format_exc()) else: # there is no hook in this dir, so we want to create one - _rhodecode_hook = True + has_hook = True - if _rhodecode_hook or force_create: + if has_hook or force_create: log.debug('writing %s hook file !' % (h_type,)) try: with open(_hook_file, 'wb') as f: - tmpl = tmpl.replace('_TMPL_', rhodecode.__version__) + tmpl = tmpl.replace('_TMPL_', kallithea.__version__) f.write(tmpl) os.chmod(_hook_file, 0755) except IOError, e: diff --git a/rhodecode/model/user.py b/kallithea/model/user.py rename from rhodecode/model/user.py rename to kallithea/model/user.py --- a/rhodecode/model/user.py +++ b/kallithea/model/user.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.user - ~~~~~~~~~~~~~~~~~~~~ - - users model for RhodeCode - - :created_on: Apr 9, 2010 - :author: marcink - :copyright: (C) 2010-2012 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -22,33 +11,41 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +kallithea.model.user +~~~~~~~~~~~~~~~~~~~~ + +users model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Apr 9, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. +""" + import logging import traceback -import itertools -import collections from pylons import url from pylons.i18n.translation import _ from sqlalchemy.exc import DatabaseError -from sqlalchemy.orm import joinedload -from rhodecode.lib.utils2 import safe_unicode, generate_api_key, get_current_rhodecode_user -from rhodecode.lib.caching_query import FromCache -from rhodecode.model import BaseModel -from rhodecode.model.db import User, Repository, Permission, \ - UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \ - Notification, RepoGroup, UserGroupRepoGroupToPerm, \ - UserEmailMap, UserIpMap, UserGroupUserGroupToPerm, UserGroup -from rhodecode.lib.exceptions import DefaultUserException, \ +from kallithea import EXTERN_TYPE_INTERNAL +from kallithea.lib.utils2 import safe_unicode, generate_api_key, get_current_authuser +from kallithea.lib.caching_query import FromCache +from kallithea.model import BaseModel +from kallithea.model.db import User, UserToPerm, Notification, \ + UserEmailMap, UserIpMap +from kallithea.lib.exceptions import DefaultUserException, \ UserOwnsReposException -from rhodecode.model.meta import Session +from kallithea.model.meta import Session log = logging.getLogger(__name__) -PERM_WEIGHTS = Permission.PERM_WEIGHTS - class UserModel(BaseModel): cls = User @@ -68,7 +65,8 @@ class UserModel(BaseModel): if case_insensitive: user = self.sa.query(User).filter(User.username.ilike(username)) else: - user = self.sa.query(User).filter(User.username == username) + user = self.sa.query(User)\ + .filter(User.username == username) if cache: user = user.options(FromCache("sql_cache_short", "get_user_%s" % username)) @@ -82,9 +80,9 @@ class UserModel(BaseModel): def create(self, form_data, cur_user=None): if not cur_user: - cur_user = getattr(get_current_rhodecode_user(), 'username', None) + cur_user = getattr(get_current_authuser(), 'username', None) - from rhodecode.lib.hooks import log_create_user, check_allowed_create_user + from kallithea.lib.hooks import log_create_user, check_allowed_create_user _fd = form_data user_data = { 'username': _fd['username'], 'password': _fd['password'], @@ -93,8 +91,7 @@ class UserModel(BaseModel): } # raises UserCreationError if it's not allowed check_allowed_create_user(user_data, cur_user) - - from rhodecode.lib.auth import get_crypt_password + from kallithea.lib.auth import get_crypt_password try: new_user = User() for k, v in form_data.items(): @@ -114,8 +111,8 @@ class UserModel(BaseModel): raise def create_or_update(self, username, password, email, firstname='', - lastname='', active=True, admin=False, ldap_dn=None, - cur_user=None): + lastname='', active=True, admin=False, + extern_type=None, extern_name=None, cur_user=None): """ Creates a new instance if not found, or updates current one @@ -127,14 +124,15 @@ class UserModel(BaseModel): :param lastname: :param active: :param admin: - :param ldap_dn: + :param extern_name: + :param extern_type: :param cur_user: """ if not cur_user: - cur_user = getattr(get_current_rhodecode_user(), 'username', None) + cur_user = getattr(get_current_authuser(), 'username', None) - from rhodecode.lib.auth import get_crypt_password - from rhodecode.lib.hooks import log_create_user, check_allowed_create_user + from kallithea.lib.auth import get_crypt_password, check_password + from kallithea.lib.hooks import log_create_user, check_allowed_create_user user_data = { 'username': username, 'password': password, 'email': email, 'firstname': firstname, 'lastname': lastname, @@ -143,7 +141,7 @@ class UserModel(BaseModel): # raises UserCreationError if it's not allowed check_allowed_create_user(user_data, cur_user) - log.debug('Checking for %s account in RhodeCode database' % username) + log.debug('Checking for %s account in Kallithea database' % username) user = User.get_by_username(username, case_insensitive=True) if user is None: log.debug('creating new user %s' % username) @@ -157,15 +155,24 @@ class UserModel(BaseModel): try: new_user.username = username new_user.admin = admin - # set password only if creating an user or password is changed - if not edit or user.password != password: - new_user.password = get_crypt_password(password) if password else None - new_user.api_key = generate_api_key(username) new_user.email = email new_user.active = active - new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None + new_user.extern_name = safe_unicode(extern_name) if extern_name else None + new_user.extern_type = safe_unicode(extern_type) if extern_type else None new_user.name = firstname new_user.lastname = lastname + + if not edit: + new_user.api_key = generate_api_key(username) + + # set password only if creating an user or password is changed + password_change = new_user.password and not check_password(password, + new_user.password) + if not edit or password_change: + reason = 'new password' if edit else 'new user' + log.debug('Updating password reason=>%s' % (reason,)) + new_user.password = get_crypt_password(password) if password else None + self.sa.add(new_user) if not edit: @@ -175,116 +182,13 @@ class UserModel(BaseModel): log.error(traceback.format_exc()) raise - def create_for_container_auth(self, username, attrs, cur_user=None): - """ - Creates the given user if it's not already in the database - - :param username: - :param attrs: - :param cur_user: - """ - if not cur_user: - cur_user = getattr(get_current_rhodecode_user(), 'username', None) - if self.get_by_username(username, case_insensitive=True) is None: - # autogenerate email for container account without one - generate_email = lambda usr: '%s@container_auth.account' % usr - firstname = attrs['name'] - lastname = attrs['lastname'] - active = attrs.get('active', True) - email = attrs['email'] or generate_email(username) - - from rhodecode.lib.hooks import log_create_user, check_allowed_create_user - user_data = { - 'username': username, 'password': None, - 'email': email, 'firstname': firstname, 'lastname': lastname, - 'active': attrs.get('active', True), 'admin': False - } - # raises UserCreationError if it's not allowed - check_allowed_create_user(user_data, cur_user) - - try: - new_user = User() - new_user.username = username - new_user.password = None - new_user.api_key = generate_api_key(username) - new_user.email = email - new_user.active = active - new_user.name = firstname - new_user.lastname = lastname - - self.sa.add(new_user) - log_create_user(new_user.get_dict(), cur_user) - return new_user - except (DatabaseError,): - log.error(traceback.format_exc()) - self.sa.rollback() - raise - log.debug('User %s already exists. Skipping creation of account' - ' for container auth.', username) - return None - - def create_ldap(self, username, password, user_dn, attrs, cur_user=None): - """ - Checks if user is in database, if not creates this user marked - as ldap user - - :param username: - :param password: - :param user_dn: - :param attrs: - :param cur_user: - """ - if not cur_user: - cur_user = getattr(get_current_rhodecode_user(), 'username', None) - from rhodecode.lib.auth import get_crypt_password - log.debug('Checking for such ldap account in RhodeCode database') - if self.get_by_username(username, case_insensitive=True) is None: - # autogenerate email for container account without one - generate_email = lambda usr: '%s@ldap.account' % usr - password = get_crypt_password(password) - firstname = attrs['name'] - lastname = attrs['lastname'] - active = attrs.get('active', True) - email = attrs['email'] or generate_email(username) - - from rhodecode.lib.hooks import log_create_user, check_allowed_create_user - user_data = { - 'username': username, 'password': password, - 'email': email, 'firstname': firstname, 'lastname': lastname, - 'active': attrs.get('active', True), 'admin': False - } - # raises UserCreationError if it's not allowed - check_allowed_create_user(user_data, cur_user) - - try: - new_user = User() - username = username.lower() - # add ldap account always lowercase - new_user.username = username - new_user.password = password - new_user.api_key = generate_api_key(username) - new_user.email = email - new_user.active = active - new_user.ldap_dn = safe_unicode(user_dn) - new_user.name = firstname - new_user.lastname = lastname - self.sa.add(new_user) - - log_create_user(new_user.get_dict(), cur_user) - return new_user - except (DatabaseError,): - log.error(traceback.format_exc()) - self.sa.rollback() - raise - log.debug('this %s user exists skipping creation of ldap account', - username) - return None - def create_registration(self, form_data): - from rhodecode.model.notification import NotificationModel + from kallithea.model.notification import NotificationModel try: form_data['admin'] = False + form_data['extern_name'] = EXTERN_TYPE_INTERNAL + form_data['extern_type'] = EXTERN_TYPE_INTERNAL new_user = self.create(form_data) self.sa.add(new_user) @@ -310,21 +214,22 @@ class UserModel(BaseModel): raise def update(self, user_id, form_data, skip_attrs=[]): - from rhodecode.lib.auth import get_crypt_password + from kallithea.lib.auth import get_crypt_password try: user = self.get(user_id, cache=False) - if user.username == 'default': + if user.username == User.DEFAULT_USER: raise DefaultUserException( - _("You can't Edit this user since it's" - " crucial for entire application")) + _("You can't Edit this user since it's " + "crucial for entire application")) for k, v in form_data.items(): if k in skip_attrs: continue if k == 'new_password' and v: user.password = get_crypt_password(v) - user.api_key = generate_api_key(user.username) else: + # old legacy thing orm models store firstname as name, + # need proper refactor to username if k == 'firstname': k = 'name' setattr(user, k, v) @@ -334,10 +239,10 @@ class UserModel(BaseModel): raise def update_user(self, user, **kwargs): - from rhodecode.lib.auth import get_crypt_password + from kallithea.lib.auth import get_crypt_password try: user = self._get_user(user) - if user.username == 'default': + if user.username == User.DEFAULT_USER: raise DefaultUserException( _("You can't Edit this user since it's" " crucial for entire application") @@ -346,7 +251,6 @@ class UserModel(BaseModel): for k, v in kwargs.items(): if k == 'password' and v: v = get_crypt_password(v) - user.api_key = generate_api_key(user.username) setattr(user, k, v) self.sa.add(user) @@ -357,11 +261,11 @@ class UserModel(BaseModel): def delete(self, user, cur_user=None): if not cur_user: - cur_user = getattr(get_current_rhodecode_user(), 'username', None) + cur_user = getattr(get_current_authuser(), 'username', None) user = self._get_user(user) try: - if user.username == 'default': + if user.username == User.DEFAULT_USER: raise DefaultUserException( _(u"You can't remove this user since it's" " crucial for entire application") @@ -375,15 +279,15 @@ class UserModel(BaseModel): ) self.sa.delete(user) - from rhodecode.lib.hooks import log_delete_user + from kallithea.lib.hooks import log_delete_user log_delete_user(user.get_dict(), cur_user) except Exception: log.error(traceback.format_exc()) raise def reset_password_link(self, data): - from rhodecode.lib.celerylib import tasks, run_task - from rhodecode.model.notification import EmailNotificationModel + from kallithea.lib.celerylib import tasks, run_task + from kallithea.model.notification import EmailNotificationModel user_email = data['email'] try: user = User.get_by_email(user_email) @@ -408,8 +312,8 @@ class UserModel(BaseModel): return True def reset_password(self, data): - from rhodecode.lib.celerylib import tasks, run_task - from rhodecode.lib import auth + from kallithea.lib.celerylib import tasks, run_task + from kallithea.lib import auth user_email = data['email'] pre_db = True try: @@ -418,7 +322,6 @@ class UserModel(BaseModel): auth.PasswordGenerator.ALPHABETS_BIG_SMALL) if user: user.password = auth.get_crypt_password(new_passwd) - user.api_key = auth.generate_api_key(user.username) Session().add(user) Session().commit() log.info('change password for %s' % user_email) @@ -428,7 +331,7 @@ class UserModel(BaseModel): pre_db = False run_task(tasks.send_email, user_email, _('Your new password'), - _('Your new RhodeCode password:%s') % (new_passwd,)) + _('Your new Kallithea password:%s') % (new_passwd,)) log.info('send new password mail to %s' % user_email) except Exception: @@ -441,7 +344,7 @@ class UserModel(BaseModel): return True - def fill_data(self, auth_user, user_id=None, api_key=None): + def fill_data(self, auth_user, user_id=None, api_key=None, username=None): """ Fetches auth_user by user_id,or api_key if present. Fills auth_user attributes with those taken from database. @@ -451,20 +354,25 @@ class UserModel(BaseModel): :param auth_user: instance of user to set attributes :param user_id: user id to fetch by :param api_key: api key to fetch by + :param username: username to fetch by """ - if user_id is None and api_key is None: - raise Exception('You need to pass user_id or api_key') + if user_id is None and api_key is None and username is None: + raise Exception('You need to pass user_id, api_key or username') try: - if api_key: + dbuser = None + if user_id: + dbuser = self.get(user_id) + elif api_key: dbuser = self.get_by_api_key(api_key) - else: - dbuser = self.get(user_id) + elif username: + dbuser = self.get_by_username(username) if dbuser is not None and dbuser.active: log.debug('filling %s data' % dbuser) - for k, v in dbuser.get_dict().items(): - setattr(auth_user, k, v) + for k, v in dbuser.get_dict().iteritems(): + if k not in ['api_keys', 'permissions']: + setattr(auth_user, k, v) else: return False @@ -475,296 +383,6 @@ class UserModel(BaseModel): return True - def fill_perms(self, user, explicit=True, algo='higherwin'): - """ - Fills user permission attribute with permissions taken from database - works for permissions given for repositories, and for permissions that - are granted to groups - - :param user: user instance to fill his perms - :param explicit: In case there are permissions both for user and a group - that user is part of, explicit flag will defiine if user will - explicitly override permissions from group, if it's False it will - make decision based on the algo - :param algo: algorithm to decide what permission should be choose if - it's multiple defined, eg user in two different groups. It also - decides if explicit flag is turned off how to specify the permission - for case when user is in a group + have defined separate permission - """ - RK = 'repositories' - GK = 'repositories_groups' - UK = 'user_groups' - GLOBAL = 'global' - user.permissions[RK] = {} - user.permissions[GK] = {} - user.permissions[UK] = {} - user.permissions[GLOBAL] = set() - - def _choose_perm(new_perm, cur_perm): - new_perm_val = PERM_WEIGHTS[new_perm] - cur_perm_val = PERM_WEIGHTS[cur_perm] - if algo == 'higherwin': - if new_perm_val > cur_perm_val: - return new_perm - return cur_perm - elif algo == 'lowerwin': - if new_perm_val < cur_perm_val: - return new_perm - return cur_perm - - #====================================================================== - # fetch default permissions - #====================================================================== - default_user = User.get_by_username('default', cache=True) - default_user_id = default_user.user_id - - default_repo_perms = Permission.get_default_perms(default_user_id) - default_repo_groups_perms = Permission.get_default_group_perms(default_user_id) - default_user_group_perms = Permission.get_default_user_group_perms(default_user_id) - - if user.is_admin: - #================================================================== - # admin user have all default rights for repositories - # and groups set to admin - #================================================================== - user.permissions[GLOBAL].add('hg.admin') - - # repositories - for perm in default_repo_perms: - r_k = perm.UserRepoToPerm.repository.repo_name - p = 'repository.admin' - user.permissions[RK][r_k] = p - - # repository groups - for perm in default_repo_groups_perms: - rg_k = perm.UserRepoGroupToPerm.group.group_name - p = 'group.admin' - user.permissions[GK][rg_k] = p - - # user groups - for perm in default_user_group_perms: - u_k = perm.UserUserGroupToPerm.user_group.users_group_name - p = 'usergroup.admin' - user.permissions[UK][u_k] = p - return user - - #================================================================== - # SET DEFAULTS GLOBAL, REPOS, REPOSITORY GROUPS - #================================================================== - uid = user.user_id - - # default global permissions taken fron the default user - default_global_perms = self.sa.query(UserToPerm)\ - .filter(UserToPerm.user_id == default_user_id) - - for perm in default_global_perms: - user.permissions[GLOBAL].add(perm.permission.permission_name) - - # defaults for repositories, taken from default user - for perm in default_repo_perms: - r_k = perm.UserRepoToPerm.repository.repo_name - if perm.Repository.private and not (perm.Repository.user_id == uid): - # disable defaults for private repos, - p = 'repository.none' - elif perm.Repository.user_id == uid: - # set admin if owner - p = 'repository.admin' - else: - p = perm.Permission.permission_name - - user.permissions[RK][r_k] = p - - # defaults for repository groups taken from default user permission - # on given group - for perm in default_repo_groups_perms: - rg_k = perm.UserRepoGroupToPerm.group.group_name - p = perm.Permission.permission_name - user.permissions[GK][rg_k] = p - - # defaults for user groups taken from default user permission - # on given user group - for perm in default_user_group_perms: - u_k = perm.UserUserGroupToPerm.user_group.users_group_name - p = perm.Permission.permission_name - user.permissions[UK][u_k] = p - - #====================================================================== - # !! OVERRIDE GLOBALS !! with user permissions if any found - #====================================================================== - # those can be configured from groups or users explicitly - _configurable = set([ - 'hg.fork.none', 'hg.fork.repository', - 'hg.create.none', 'hg.create.repository', - 'hg.usergroup.create.false', 'hg.usergroup.create.true' - ]) - - # USER GROUPS comes first - # user group global permissions - user_perms_from_users_groups = self.sa.query(UserGroupToPerm)\ - .options(joinedload(UserGroupToPerm.permission))\ - .join((UserGroupMember, UserGroupToPerm.users_group_id == - UserGroupMember.users_group_id))\ - .filter(UserGroupMember.user_id == uid)\ - .order_by(UserGroupToPerm.users_group_id)\ - .all() - #need to group here by groups since user can be in more than one group - _grouped = [[x, list(y)] for x, y in - itertools.groupby(user_perms_from_users_groups, - lambda x:x.users_group)] - for gr, perms in _grouped: - # since user can be in multiple groups iterate over them and - # select the lowest permissions first (more explicit) - ##TODO: do this^^ - if not gr.inherit_default_permissions: - # NEED TO IGNORE all configurable permissions and - # replace them with explicitly set - user.permissions[GLOBAL] = user.permissions[GLOBAL]\ - .difference(_configurable) - for perm in perms: - user.permissions[GLOBAL].add(perm.permission.permission_name) - - # user specific global permissions - user_perms = self.sa.query(UserToPerm)\ - .options(joinedload(UserToPerm.permission))\ - .filter(UserToPerm.user_id == uid).all() - - if not user.inherit_default_permissions: - # NEED TO IGNORE all configurable permissions and - # replace them with explicitly set - user.permissions[GLOBAL] = user.permissions[GLOBAL]\ - .difference(_configurable) - - for perm in user_perms: - user.permissions[GLOBAL].add(perm.permission.permission_name) - ## END GLOBAL PERMISSIONS - - #====================================================================== - # !! PERMISSIONS FOR REPOSITORIES !! - #====================================================================== - #====================================================================== - # check if user is part of user groups for this repository and - # fill in his permission from it. _choose_perm decides of which - # permission should be selected based on selected method - #====================================================================== - - # user group for repositories permissions - user_repo_perms_from_users_groups = \ - self.sa.query(UserGroupRepoToPerm, Permission, Repository,)\ - .join((Repository, UserGroupRepoToPerm.repository_id == - Repository.repo_id))\ - .join((Permission, UserGroupRepoToPerm.permission_id == - Permission.permission_id))\ - .join((UserGroupMember, UserGroupRepoToPerm.users_group_id == - UserGroupMember.users_group_id))\ - .filter(UserGroupMember.user_id == uid)\ - .all() - - multiple_counter = collections.defaultdict(int) - for perm in user_repo_perms_from_users_groups: - r_k = perm.UserGroupRepoToPerm.repository.repo_name - multiple_counter[r_k] += 1 - p = perm.Permission.permission_name - cur_perm = user.permissions[RK][r_k] - - if perm.Repository.user_id == uid: - # set admin if owner - p = 'repository.admin' - else: - if multiple_counter[r_k] > 1: - p = _choose_perm(p, cur_perm) - user.permissions[RK][r_k] = p - - # user explicit permissions for repositories, overrides any specified - # by the group permission - user_repo_perms = Permission.get_default_perms(uid) - for perm in user_repo_perms: - r_k = perm.UserRepoToPerm.repository.repo_name - cur_perm = user.permissions[RK][r_k] - # set admin if owner - if perm.Repository.user_id == uid: - p = 'repository.admin' - else: - p = perm.Permission.permission_name - if not explicit: - p = _choose_perm(p, cur_perm) - user.permissions[RK][r_k] = p - - #====================================================================== - # !! PERMISSIONS FOR REPOSITORY GROUPS !! - #====================================================================== - #====================================================================== - # check if user is part of user groups for this repository groups and - # fill in his permission from it. _choose_perm decides of which - # permission should be selected based on selected method - #====================================================================== - # user group for repo groups permissions - user_repo_group_perms_from_users_groups = \ - self.sa.query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\ - .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\ - .join((Permission, UserGroupRepoGroupToPerm.permission_id - == Permission.permission_id))\ - .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id - == UserGroupMember.users_group_id))\ - .filter(UserGroupMember.user_id == uid)\ - .all() - - multiple_counter = collections.defaultdict(int) - for perm in user_repo_group_perms_from_users_groups: - g_k = perm.UserGroupRepoGroupToPerm.group.group_name - multiple_counter[g_k] += 1 - p = perm.Permission.permission_name - cur_perm = user.permissions[GK][g_k] - if multiple_counter[g_k] > 1: - p = _choose_perm(p, cur_perm) - user.permissions[GK][g_k] = p - - # user explicit permissions for repository groups - user_repo_groups_perms = Permission.get_default_group_perms(uid) - for perm in user_repo_groups_perms: - rg_k = perm.UserRepoGroupToPerm.group.group_name - p = perm.Permission.permission_name - cur_perm = user.permissions[GK][rg_k] - if not explicit: - p = _choose_perm(p, cur_perm) - user.permissions[GK][rg_k] = p - - #====================================================================== - # !! PERMISSIONS FOR USER GROUPS !! - #====================================================================== - # user group for user group permissions - user_group_user_groups_perms = \ - self.sa.query(UserGroupUserGroupToPerm, Permission, UserGroup)\ - .join((UserGroup, UserGroupUserGroupToPerm.target_user_group_id - == UserGroup.users_group_id))\ - .join((Permission, UserGroupUserGroupToPerm.permission_id - == Permission.permission_id))\ - .join((UserGroupMember, UserGroupUserGroupToPerm.user_group_id - == UserGroupMember.users_group_id))\ - .filter(UserGroupMember.user_id == uid)\ - .all() - - multiple_counter = collections.defaultdict(int) - for perm in user_group_user_groups_perms: - g_k = perm.UserGroupUserGroupToPerm.target_user_group.users_group_name - multiple_counter[g_k] += 1 - p = perm.Permission.permission_name - cur_perm = user.permissions[UK][g_k] - if multiple_counter[g_k] > 1: - p = _choose_perm(p, cur_perm) - user.permissions[UK][g_k] = p - - #user explicit permission for user groups - user_user_groups_perms = Permission.get_default_user_group_perms(uid) - for perm in user_user_groups_perms: - u_k = perm.UserUserGroupToPerm.user_group.users_group_name - p = perm.Permission.permission_name - cur_perm = user.permissions[UK][u_k] - if not explicit: - p = _choose_perm(p, cur_perm) - user.permissions[UK][u_k] = p - - return user - def has_perm(self, user, perm): perm = self._get_perm(perm) user = self._get_user(user) @@ -792,6 +410,7 @@ class UserModel(BaseModel): new.user = user new.permission = perm self.sa.add(new) + return new def revoke_perm(self, user, perm): """ @@ -817,7 +436,7 @@ class UserModel(BaseModel): :param user: :param email: """ - from rhodecode.model import forms + from kallithea.model import forms form = forms.UserExtraEmailForm()() data = form.to_python(dict(email=email)) user = self._get_user(user) @@ -847,7 +466,7 @@ class UserModel(BaseModel): :param user: :param ip: """ - from rhodecode.model import forms + from kallithea.model import forms form = forms.UserExtraIpForm()() data = form.to_python(dict(ip=ip)) user = self._get_user(user) diff --git a/kallithea/model/user_group.py b/kallithea/model/user_group.py new file mode 100644 --- /dev/null +++ b/kallithea/model/user_group.py @@ -0,0 +1,389 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +kallithea.model.users_group +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +user group model for Kallithea + +This file was forked by the Kallithea project in July 2014. +Original author and date, and relevant copyright and licensing information is below: +:created_on: Oct 1, 2011 +:author: nvinot, marcink +""" + + +import logging +import traceback + +from kallithea.model import BaseModel +from kallithea.model.db import UserGroupMember, UserGroup,\ + UserGroupRepoToPerm, Permission, UserGroupToPerm, User, UserUserGroupToPerm,\ + UserGroupUserGroupToPerm +from kallithea.lib.exceptions import UserGroupsAssignedException,\ + RepoGroupAssignmentError + +log = logging.getLogger(__name__) + + +class UserGroupModel(BaseModel): + + cls = UserGroup + + def _get_user_group(self, user_group): + return self._get_instance(UserGroup, user_group, + callback=UserGroup.get_by_group_name) + + def _create_default_perms(self, user_group): + # create default permission + default_perm = 'usergroup.read' + def_user = User.get_default_user() + for p in def_user.user_perms: + if p.permission.permission_name.startswith('usergroup.'): + default_perm = p.permission.permission_name + break + + user_group_to_perm = UserUserGroupToPerm() + user_group_to_perm.permission = Permission.get_by_key(default_perm) + + user_group_to_perm.user_group = user_group + user_group_to_perm.user_id = def_user.user_id + return user_group_to_perm + + def _update_permissions(self, user_group, perms_new=None, + perms_updates=None): + from kallithea.lib.auth import HasUserGroupPermissionAny + if not perms_new: + perms_new = [] + if not perms_updates: + perms_updates = [] + + # update permissions + for member, perm, member_type in perms_updates: + if member_type == 'user': + # this updates existing one + self.grant_user_permission( + user_group=user_group, user=member, perm=perm + ) + else: + #check if we have permissions to alter this usergroup + if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write', + 'usergroup.admin')(member): + self.grant_user_group_permission( + target_user_group=user_group, user_group=member, perm=perm + ) + # set new permissions + for member, perm, member_type in perms_new: + if member_type == 'user': + self.grant_user_permission( + user_group=user_group, user=member, perm=perm + ) + else: + #check if we have permissions to alter this usergroup + if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write', + 'usergroup.admin')(member): + self.grant_user_group_permission( + target_user_group=user_group, user_group=member, perm=perm + ) + + def get(self, user_group_id, cache=False): + return UserGroup.get(user_group_id) + + def get_group(self, user_group): + return self._get_user_group(user_group) + + def get_by_name(self, name, cache=False, case_insensitive=False): + return UserGroup.get_by_group_name(name, cache, case_insensitive) + + def create(self, name, description, owner, active=True, group_data=None): + try: + new_user_group = UserGroup() + new_user_group.user = self._get_user(owner) + new_user_group.users_group_name = name + new_user_group.user_group_description = description + new_user_group.users_group_active = active + if group_data: + new_user_group.group_data = group_data + self.sa.add(new_user_group) + perm_obj = self._create_default_perms(new_user_group) + self.sa.add(perm_obj) + + self.grant_user_permission(user_group=new_user_group, + user=owner, perm='usergroup.admin') + + return new_user_group + except Exception: + log.error(traceback.format_exc()) + raise + + def update(self, user_group, form_data): + + try: + user_group = self._get_user_group(user_group) + + for k, v in form_data.items(): + if k == 'users_group_members': + user_group.members = [] + self.sa.flush() + members_list = [] + if v: + v = [v] if isinstance(v, basestring) else v + for u_id in set(v): + member = UserGroupMember(user_group.users_group_id, u_id) + members_list.append(member) + setattr(user_group, 'members', members_list) + setattr(user_group, k, v) + + self.sa.add(user_group) + except Exception: + log.error(traceback.format_exc()) + raise + + def delete(self, user_group, force=False): + """ + Deletes repository group, unless force flag is used + raises exception if there are members in that group, else deletes + group and users + + :param user_group: + :param force: + """ + user_group = self._get_user_group(user_group) + try: + # check if this group is not assigned to repo + assigned_groups = UserGroupRepoToPerm.query()\ + .filter(UserGroupRepoToPerm.users_group == user_group).all() + + if assigned_groups and not force: + raise UserGroupsAssignedException( + 'RepoGroup assigned to %s' % assigned_groups) + self.sa.delete(user_group) + except Exception: + log.error(traceback.format_exc()) + raise + + def add_user_to_group(self, user_group, user): + user_group = self._get_user_group(user_group) + user = self._get_user(user) + + for m in user_group.members: + u = m.user + if u.user_id == user.user_id: + # user already in the group, skip + return True + + try: + user_group_member = UserGroupMember() + user_group_member.user = user + user_group_member.users_group = user_group + + user_group.members.append(user_group_member) + user.group_member.append(user_group_member) + + self.sa.add(user_group_member) + return user_group_member + except Exception: + log.error(traceback.format_exc()) + raise + + def remove_user_from_group(self, user_group, user): + user_group = self._get_user_group(user_group) + user = self._get_user(user) + + user_group_member = None + for m in user_group.members: + if m.user.user_id == user.user_id: + # Found this user's membership row + user_group_member = m + break + + if user_group_member: + try: + self.sa.delete(user_group_member) + return True + except Exception: + log.error(traceback.format_exc()) + raise + else: + # User isn't in that group + return False + + def has_perm(self, user_group, perm): + user_group = self._get_user_group(user_group) + perm = self._get_perm(perm) + + return UserGroupToPerm.query()\ + .filter(UserGroupToPerm.users_group == user_group)\ + .filter(UserGroupToPerm.permission == perm).scalar() is not None + + def grant_perm(self, user_group, perm): + user_group = self._get_user_group(user_group) + perm = self._get_perm(perm) + + # if this permission is already granted skip it + _perm = UserGroupToPerm.query()\ + .filter(UserGroupToPerm.users_group == user_group)\ + .filter(UserGroupToPerm.permission == perm)\ + .scalar() + if _perm: + return + + new = UserGroupToPerm() + new.users_group = user_group + new.permission = perm + self.sa.add(new) + return new + + def revokehas_permrevoke_permgrant_perm_perm(self, user_group, perm): + user_group = self._get_user_group(user_group) + perm = self._get_perm(perm) + + obj = UserGroupToPerm.query()\ + .filter(UserGroupToPerm.users_group == user_group)\ + .filter(UserGroupToPerm.permission == perm).scalar() + if obj: + self.sa.delete(obj) + + def grant_user_permission(self, user_group, user, perm): + """ + Grant permission for user on given user group, or update + existing one if found + + :param user_group: Instance of UserGroup, users_group_id, + or users_group_name + :param user: Instance of User, user_id or username + :param perm: Instance of Permission, or permission_name + """ + + user_group = self._get_user_group(user_group) + user = self._get_user(user) + permission = self._get_perm(perm) + + # check if we have that permission already + obj = self.sa.query(UserUserGroupToPerm)\ + .filter(UserUserGroupToPerm.user == user)\ + .filter(UserUserGroupToPerm.user_group == user_group)\ + .scalar() + if obj is None: + # create new ! + obj = UserUserGroupToPerm() + obj.user_group = user_group + obj.user = user + obj.permission = permission + self.sa.add(obj) + log.debug('Granted perm %s to %s on %s' % (perm, user, user_group)) + return obj + + def revoke_user_permission(self, user_group, user): + """ + Revoke permission for user on given repository group + + :param user_group: Instance of RepoGroup, repositories_group_id, + or repositories_group name + :param user: Instance of User, user_id or username + """ + + user_group = self._get_user_group(user_group) + user = self._get_user(user) + + obj = self.sa.query(UserUserGroupToPerm)\ + .filter(UserUserGroupToPerm.user == user)\ + .filter(UserUserGroupToPerm.user_group == user_group)\ + .scalar() + if obj: + self.sa.delete(obj) + log.debug('Revoked perm on %s on %s' % (user_group, user)) + + def grant_user_group_permission(self, target_user_group, user_group, perm): + """ + Grant user group permission for given target_user_group + + :param target_user_group: + :param user_group: + :param perm: + """ + target_user_group = self._get_user_group(target_user_group) + user_group = self._get_user_group(user_group) + permission = self._get_perm(perm) + # forbid assigning same user group to itself + if target_user_group == user_group: + raise RepoGroupAssignmentError('target repo:%s cannot be ' + 'assigned to itself' % target_user_group) + + # check if we have that permission already + obj = self.sa.query(UserGroupUserGroupToPerm)\ + .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\ + .filter(UserGroupUserGroupToPerm.user_group == user_group)\ + .scalar() + if obj is None: + # create new ! + obj = UserGroupUserGroupToPerm() + obj.user_group = user_group + obj.target_user_group = target_user_group + obj.permission = permission + self.sa.add(obj) + log.debug('Granted perm %s to %s on %s' % (perm, target_user_group, user_group)) + return obj + + def revoke_user_group_permission(self, target_user_group, user_group): + """ + Revoke user group permission for given target_user_group + + :param target_user_group: + :param user_group: + """ + target_user_group = self._get_user_group(target_user_group) + user_group = self._get_user_group(user_group) + + obj = self.sa.query(UserGroupUserGroupToPerm)\ + .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\ + .filter(UserGroupUserGroupToPerm.user_group == user_group)\ + .scalar() + if obj: + self.sa.delete(obj) + log.debug('Revoked perm on %s on %s' % (target_user_group, user_group)) + + def enforce_groups(self, user, groups, extern_type=None): + user = self._get_user(user) + log.debug('Enforcing groups %s on user %s' % (user, groups)) + current_groups = user.group_member + # find the external created groups + externals = [x.users_group for x in current_groups + if 'extern_type' in x.users_group.group_data] + + # calculate from what groups user should be removed + # externals that are not in groups + for gr in externals: + if gr.users_group_name not in groups: + log.debug('Removing user %s from user group %s' % (user, gr)) + self.remove_user_from_group(gr, user) + + # now we calculate in which groups user should be == groups params + owner = User.get_first_admin().username + for gr in set(groups): + existing_group = UserGroup.get_by_group_name(gr) + if not existing_group: + desc = 'Automatically created from plugin:%s' % extern_type + # we use first admin account to set the owner of the group + existing_group = UserGroupModel().create(gr, desc, owner, + group_data={'extern_type': extern_type}) + + # we can only add users to special groups created via plugins + managed = 'extern_type' in existing_group.group_data + if managed: + log.debug('Adding user %s to user group %s' % (user, gr)) + UserGroupModel().add_user_to_group(existing_group, user) + else: + log.debug('Skipping addition to group %s since it is ' + 'not managed by auth plugins' % gr) diff --git a/rhodecode/model/validators.py b/kallithea/model/validators.py rename from rhodecode/model/validators.py rename to kallithea/model/validators.py --- a/rhodecode/model/validators.py +++ b/kallithea/model/validators.py @@ -1,6 +1,20 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . """ Set of generic validators """ + import os import re import formencode @@ -13,15 +27,15 @@ from formencode.validators import ( UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set, NotEmpty, IPAddress, CIDR, String, FancyValidator ) -from rhodecode.lib.compat import OrderedSet -from rhodecode.lib import ipaddr -from rhodecode.lib.utils import repo_name_slug -from rhodecode.lib.utils2 import safe_int, str2bool -from rhodecode.model.db import RepoGroup, Repository, UserGroup, User,\ +from kallithea.lib.compat import OrderedSet +from kallithea.lib import ipaddr +from kallithea.lib.utils import repo_name_slug +from kallithea.lib.utils2 import safe_int, str2bool, aslist +from kallithea.model.db import RepoGroup, Repository, UserGroup, User,\ ChangesetStatus -from rhodecode.lib.exceptions import LdapImportError -from rhodecode.config.routing import ADMIN_PREFIX -from rhodecode.lib.auth import HasReposGroupPermissionAny, HasPermissionAny +from kallithea.lib.exceptions import LdapImportError +from kallithea.config.routing import ADMIN_PREFIX +from kallithea.lib.auth import HasRepoGroupPermissionAny, HasPermissionAny # silence warnings and pylint UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set, \ @@ -29,30 +43,10 @@ UnicodeString, OneOf, Int, Number, Regex log = logging.getLogger(__name__) - -class UniqueList(formencode.FancyValidator): - """ - Unique List ! - """ - messages = dict( - empty=_('Value cannot be an empty list'), - missing_value=_('Value cannot be an empty list'), - ) +class _Missing(object): + pass - def _to_python(self, value, state): - if isinstance(value, list): - return value - elif isinstance(value, set): - return list(value) - elif isinstance(value, tuple): - return list(value) - elif value is None: - return [] - else: - return [value] - - def empty_value(self, value): - return [] +Missing = _Missing() class StateObj(object): @@ -79,6 +73,47 @@ def M(self, key, state=None, **kwargs): return self.message(key, state, **kwargs) +def UniqueList(): + class _UniqueList(formencode.FancyValidator): + """ + Unique List ! + """ + messages = dict( + empty=_('Value cannot be an empty list'), + missing_value=_('Value cannot be an empty list'), + ) + + def _to_python(self, value, state): + def make_unique(value): + seen = [] + return [c for c in value if not (c in seen or seen.append(c))] + + if isinstance(value, list): + return make_unique(value) + elif isinstance(value, set): + return make_unique(list(value)) + elif isinstance(value, tuple): + return make_unique(list(value)) + elif value is None: + return [] + else: + return [value] + + def empty_value(self, value): + return [] + + return _UniqueList + + +def UniqueListFromString(): + class _UniqueListFromString(UniqueList()): + def _to_python(self, value, state): + if isinstance(value, basestring): + value = aslist(value, ',') + return super(_UniqueListFromString, self)._to_python(value, state) + return _UniqueListFromString + + def ValidUsername(edit=False, old_data={}): class _validator(formencode.validators.FancyValidator): messages = { @@ -111,6 +146,12 @@ def ValidUsername(edit=False, old_data={ return _validator +def ValidRegex(msg=None): + class _validator(formencode.validators.Regex): + messages = dict(invalid=msg or _('The input is not valid')) + return _validator + + def ValidRepoUser(): class _validator(formencode.validators.FancyValidator): messages = { @@ -171,7 +212,7 @@ def ValidUserGroup(edit=False, old_data= return _validator -def ValidReposGroup(edit=False, old_data={}): +def ValidRepoGroup(edit=False, old_data={}): class _validator(formencode.validators.FancyValidator): messages = { 'group_parent_id': _(u'Cannot assign this group as parent'), @@ -247,7 +288,23 @@ def ValidPassword(): return _validator -def ValidPasswordsMatch(): +def ValidOldPassword(username): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_password': _(u'Invalid old password') + } + + def validate_python(self, value, state): + from kallithea.lib import auth_modules + if not auth_modules.authenticate(username, value, ''): + msg = M(self, 'invalid_password', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(current_password=msg) + ) + return _validator + + +def ValidPasswordsMatch(passwd='new_password', passwd_confirmation='password_confirmation'): class _validator(formencode.validators.FancyValidator): messages = { 'password_mismatch': _(u'Passwords do not match'), @@ -255,11 +312,11 @@ def ValidPasswordsMatch(): def validate_python(self, value, state): - pass_val = value.get('password') or value.get('new_password') - if pass_val != value['password_confirmation']: + pass_val = value.get('password') or value.get(passwd) + if pass_val != value[passwd_confirmation]: msg = M(self, 'password_mismatch', state) raise formencode.Invalid(msg, value, state, - error_dict=dict(password_confirmation=msg) + error_dict={passwd:msg, passwd_confirmation: msg} ) return _validator @@ -273,12 +330,12 @@ def ValidAuth(): } def validate_python(self, value, state): - from rhodecode.lib.auth import authenticate + from kallithea.lib import auth_modules password = value['password'] username = value['username'] - if not authenticate(username, password): + if not auth_modules.authenticate(username, password): user = User.get_by_username(username) if user and not user.active: log.warning('user %s is disabled' % username) @@ -401,30 +458,28 @@ def SlugifyName(): def ValidCloneUri(): - from rhodecode.lib.utils import make_ui + from kallithea.lib.utils import make_ui - def url_handler(repo_type, url, ui=None): + def url_handler(repo_type, url, ui): if repo_type == 'hg': - from rhodecode.lib.vcs.backends.hg.repository import MercurialRepository - from rhodecode.lib.vcs.utils.hgcompat import httppeer + from kallithea.lib.vcs.backends.hg.repository import MercurialRepository if url.startswith('http'): - ## initially check if it's at least the proper URL - ## or does it pass basic auth - MercurialRepository._check_url(url) - httppeer(ui, url)._capabilities() + # initially check if it's at least the proper URL + # or does it pass basic auth + MercurialRepository._check_url(url, ui) elif url.startswith('svn+http'): from hgsubversion.svnrepo import svnremoterepo - svnremoterepo(ui, url).capabilities + svnremoterepo(ui, url).svn.uuid elif url.startswith('git+http'): raise NotImplementedError() else: raise Exception('clone from URI %s not allowed' % (url,)) elif repo_type == 'git': - from rhodecode.lib.vcs.backends.git.repository import GitRepository + from kallithea.lib.vcs.backends.git.repository import GitRepository if url.startswith('http'): - ## initially check if it's at least the proper URL - ## or does it pass basic auth + # initially check if it's at least the proper URL + # or does it pass basic auth GitRepository._check_url(url) elif url.startswith('svn+http'): raise NotImplementedError() @@ -491,11 +546,23 @@ def CanWriteGroup(old_data=None): def validate_python(self, value, state): gr = RepoGroup.get(value) gr_name = gr.group_name if gr else None # None means ROOT location - val = HasReposGroupPermissionAny('group.write', 'group.admin') + # create repositories with write permission on group is set to true + create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')() + group_admin = HasRepoGroupPermissionAny('group.admin')(gr_name, + 'can write into group validator') + group_write = HasRepoGroupPermissionAny('group.write')(gr_name, + 'can write into group validator') + forbidden = not (group_admin or (group_write and create_on_write)) can_create_repos = HasPermissionAny('hg.admin', 'hg.create.repository') - forbidden = not val(gr_name, 'can write into group validator') - value_changed = True # old_data['repo_group'].get('group_id') != safe_int(value) - if value_changed: # do check if we changed the value + gid = (old_data['repo_group'].get('group_id') + if (old_data and 'repo_group' in old_data) else None) + value_changed = gid != safe_int(value) + new = not old_data + # do check if we changed the value, there's a case that someone got + # revoked write permissions to a repository, he still created, we + # don't need to check permission if he didn't change the value of + # groups in form box + if value_changed or new: #parent group need to be existing if gr and forbidden: msg = M(self, 'permission_denied', state) @@ -534,7 +601,7 @@ def CanCreateGroup(can_create_in_root=Fa return forbidden_in_root = gr is None and not can_create_in_root - val = HasReposGroupPermissionAny('group.admin') + val = HasRepoGroupPermissionAny('group.admin') forbidden = not val(gr_name, 'can create group validator') if forbidden_in_root or forbidden: msg = M(self, 'permission_denied', state) @@ -592,7 +659,7 @@ def ValidPerms(type_='repo'): t = {'u': 'user', 'g': 'users_group' }[k[0]] - if member == 'default': + if member == User.DEFAULT_USER: if str2bool(value.get('repo_private')): # set none for default when updating to # private repo protects agains form manipulation @@ -718,7 +785,7 @@ def LdapLibValidator(): def AttrLoginValidator(): - class _validator(formencode.validators.FancyValidator): + class _validator(formencode.validators.UnicodeString): messages = { 'invalid_cn': _(u'The LDAP Login attribute of the CN must be specified - ' @@ -825,3 +892,33 @@ def BasePath(): raise formencode.Invalid(self.message('badPath', state), value, state) return _validator + + +def ValidAuthPlugins(): + class _validator(formencode.validators.FancyValidator): + messages = dict( + import_duplicate=_('Plugins %(loaded)s and %(next_to_load)s both export the same name') + ) + + def _to_python(self, value, state): + # filter empty values + return filter(lambda s: s not in [None, ''], value) + + def validate_python(self, value, state): + from kallithea.lib import auth_modules + module_list = value + unique_names = {} + try: + for module in module_list: + plugin = auth_modules.loadplugin(module) + plugin_name = plugin.name + if plugin_name in unique_names: + msg = M(self, 'import_duplicate', state, + loaded=unique_names[plugin_name], + next_to_load=plugin_name) + raise formencode.Invalid(msg, value, state) + unique_names[plugin_name] = plugin + except (ImportError, AttributeError, TypeError), e: + raise formencode.Invalid(str(e), value, state) + + return _validator diff --git a/kallithea/public/css/bootstrap.css b/kallithea/public/css/bootstrap.css new file mode 100644 --- /dev/null +++ b/kallithea/public/css/bootstrap.css @@ -0,0 +1,6805 @@ +/*! + * Bootstrap v3.0.0 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @mdo and @fat. + */ + +/*! normalize.css v2.1.0 | MIT License | git.io/normalize */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +audio, +canvas, +video { + display: inline-block; +} + +audio:not([controls]) { + display: none; + height: 0; +} + +[hidden] { + display: none; +} + +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +body { + margin: 0; +} + +a:focus { + outline: thin dotted; +} + +a:active, +a:hover { + outline: 0; +} + +h1 { + margin: 0.67em 0; + font-size: 2em; +} + +abbr[title] { + border-bottom: 1px dotted; +} + +b, +strong { + font-weight: bold; +} + +dfn { + font-style: italic; +} + +hr { + height: 0; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +mark { + color: #000; + background: #ff0; +} + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} + +pre { + white-space: pre-wrap; +} + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + border: 0; +} + +svg:not(:root) { + overflow: hidden; +} + +figure { + margin: 0; +} + +fieldset { + padding: 0.35em 0.625em 0.75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} + +legend { + padding: 0; + border: 0; +} + +button, +input, +select, +textarea { + margin: 0; + font-family: inherit; + font-size: 100%; +} + +button, +input { + line-height: normal; +} + +button, +select { + text-transform: none; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} + +button[disabled], +html input[disabled] { + cursor: default; +} + +input[type="checkbox"], +input[type="radio"] { + padding: 0; + box-sizing: border-box; +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + @page { + margin: 2cm .5cm; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #fff !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} + +*, +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +html { + font-size: 62.5%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.428571429; + color: #333333; + background-color: #ffffff; +} + +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input, +select[multiple], +textarea { + background-image: none; +} + +a { + color: #428bca; + text-decoration: none; +} + +a:hover, +a:focus { + color: #2a6496; + text-decoration: underline; +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +img { + vertical-align: middle; +} + +.img-responsive { + display: block; + height: auto; + max-width: 100%; +} + +.img-rounded { + border-radius: 6px; +} + +.img-thumbnail { + display: inline-block; + height: auto; + max-width: 100%; + padding: 4px; + line-height: 1.428571429; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +.img-circle { + border-radius: 50%; +} + +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0 0 0 0); + border: 0; +} + +p { + margin: 0 0 10px; +} + +.lead { + margin-bottom: 20px; + font-size: 16.099999999999998px; + font-weight: 200; + line-height: 1.4; +} + +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} + +small { + font-size: 85%; +} + +cite { + font-style: normal; +} + +.text-muted { + color: #999999; +} + +.text-primary { + color: #428bca; +} + +.text-warning { + color: #c09853; +} + +.text-danger { + color: #b94a48; +} + +.text-success { + color: #468847; +} + +.text-info { + color: #3a87ad; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-center { + text-align: center; +} + +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: 500; + line-height: 1.1; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small { + font-weight: normal; + line-height: 1; + color: #999999; +} + +h1, +h2, +h3 { + margin-top: 20px; + margin-bottom: 10px; +} + +h4, +h5, +h6 { + margin-top: 10px; + margin-bottom: 10px; +} + +h1, +.h1 { + font-size: 36px; +} + +h2, +.h2 { + font-size: 30px; +} + +h3, +.h3 { + font-size: 24px; +} + +h4, +.h4 { + font-size: 18px; +} + +h5, +.h5 { + font-size: 14px; +} + +h6, +.h6 { + font-size: 12px; +} + +h1 small, +.h1 small { + font-size: 24px; +} + +h2 small, +.h2 small { + font-size: 18px; +} + +h3 small, +.h3 small, +h4 small, +.h4 small { + font-size: 14px; +} + +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} + +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} + +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} + +dl { + margin-bottom: 20px; +} + +dt, +dd { + line-height: 1.428571429; +} + +dt { + font-weight: bold; +} + +dd { + margin-left: 0; +} + +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } + .dl-horizontal dd:before, + .dl-horizontal dd:after { + display: table; + content: " "; + } + .dl-horizontal dd:after { + clear: both; + } + .dl-horizontal dd:before, + .dl-horizontal dd:after { + display: table; + content: " "; + } + .dl-horizontal dd:after { + clear: both; + } +} + +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} + +blockquote p { + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} + +blockquote p:last-child { + margin-bottom: 0; +} + +blockquote small { + display: block; + line-height: 1.428571429; + color: #999999; +} + +blockquote small:before { + content: '\2014 \00A0'; +} + +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} + +blockquote.pull-right small:before { + content: ''; +} + +blockquote.pull-right small:after { + content: '\00A0 \2014'; +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 1.428571429; +} + +code, +pre { + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; +} + +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + white-space: nowrap; + background-color: #f9f2f4; + border-radius: 4px; +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.428571429; + color: #333333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} + +pre.prettyprint { + margin-bottom: 20px; +} + +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border: 0; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +.container:before, +.container:after { + display: table; + content: " "; +} + +.container:after { + clear: both; +} + +.container:before, +.container:after { + display: table; + content: " "; +} + +.container:after { + clear: both; +} + +.row { + margin-right: -15px; + margin-left: -15px; +} + +.row:before, +.row:after { + display: table; + content: " "; +} + +.row:after { + clear: both; +} + +.row:before, +.row:after { + display: table; + content: " "; +} + +.row:after { + clear: both; +} + +.col-xs-1, +.col-xs-2, +.col-xs-3, +.col-xs-4, +.col-xs-5, +.col-xs-6, +.col-xs-7, +.col-xs-8, +.col-xs-9, +.col-xs-10, +.col-xs-11, +.col-xs-12, +.col-sm-1, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-sm-5, +.col-sm-6, +.col-sm-7, +.col-sm-8, +.col-sm-9, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-md-1, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-10, +.col-md-11, +.col-md-12, +.col-lg-1, +.col-lg-2, +.col-lg-3, +.col-lg-4, +.col-lg-5, +.col-lg-6, +.col-lg-7, +.col-lg-8, +.col-lg-9, +.col-lg-10, +.col-lg-11, +.col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} + +.col-xs-1, +.col-xs-2, +.col-xs-3, +.col-xs-4, +.col-xs-5, +.col-xs-6, +.col-xs-7, +.col-xs-8, +.col-xs-9, +.col-xs-10, +.col-xs-11 { + float: left; +} + +.col-xs-1 { + width: 8.333333333333332%; +} + +.col-xs-2 { + width: 16.666666666666664%; +} + +.col-xs-3 { + width: 25%; +} + +.col-xs-4 { + width: 33.33333333333333%; +} + +.col-xs-5 { + width: 41.66666666666667%; +} + +.col-xs-6 { + width: 50%; +} + +.col-xs-7 { + width: 58.333333333333336%; +} + +.col-xs-8 { + width: 66.66666666666666%; +} + +.col-xs-9 { + width: 75%; +} + +.col-xs-10 { + width: 83.33333333333334%; +} + +.col-xs-11 { + width: 91.66666666666666%; +} + +.col-xs-12 { + width: 100%; +} + +@media (min-width: 768px) { + .container { + max-width: 750px; + } + .col-sm-1, + .col-sm-2, + .col-sm-3, + .col-sm-4, + .col-sm-5, + .col-sm-6, + .col-sm-7, + .col-sm-8, + .col-sm-9, + .col-sm-10, + .col-sm-11 { + float: left; + } + .col-sm-1 { + width: 8.333333333333332%; + } + .col-sm-2 { + width: 16.666666666666664%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-4 { + width: 33.33333333333333%; + } + .col-sm-5 { + width: 41.66666666666667%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-7 { + width: 58.333333333333336%; + } + .col-sm-8 { + width: 66.66666666666666%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-10 { + width: 83.33333333333334%; + } + .col-sm-11 { + width: 91.66666666666666%; + } + .col-sm-12 { + width: 100%; + } + .col-sm-push-1 { + left: 8.333333333333332%; + } + .col-sm-push-2 { + left: 16.666666666666664%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-4 { + left: 33.33333333333333%; + } + .col-sm-push-5 { + left: 41.66666666666667%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-7 { + left: 58.333333333333336%; + } + .col-sm-push-8 { + left: 66.66666666666666%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-10 { + left: 83.33333333333334%; + } + .col-sm-push-11 { + left: 91.66666666666666%; + } + .col-sm-pull-1 { + right: 8.333333333333332%; + } + .col-sm-pull-2 { + right: 16.666666666666664%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-4 { + right: 33.33333333333333%; + } + .col-sm-pull-5 { + right: 41.66666666666667%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-7 { + right: 58.333333333333336%; + } + .col-sm-pull-8 { + right: 66.66666666666666%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-10 { + right: 83.33333333333334%; + } + .col-sm-pull-11 { + right: 91.66666666666666%; + } + .col-sm-offset-1 { + margin-left: 8.333333333333332%; + } + .col-sm-offset-2 { + margin-left: 16.666666666666664%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-4 { + margin-left: 33.33333333333333%; + } + .col-sm-offset-5 { + margin-left: 41.66666666666667%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-7 { + margin-left: 58.333333333333336%; + } + .col-sm-offset-8 { + margin-left: 66.66666666666666%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-10 { + margin-left: 83.33333333333334%; + } + .col-sm-offset-11 { + margin-left: 91.66666666666666%; + } +} + +@media (min-width: 992px) { + .container { + max-width: 970px; + } + .col-md-1, + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6, + .col-md-7, + .col-md-8, + .col-md-9, + .col-md-10, + .col-md-11 { + float: left; + } + .col-md-1 { + width: 8.333333333333332%; + } + .col-md-2 { + width: 16.666666666666664%; + } + .col-md-3 { + width: 25%; + } + .col-md-4 { + width: 33.33333333333333%; + } + .col-md-5 { + width: 41.66666666666667%; + } + .col-md-6 { + width: 50%; + } + .col-md-7 { + width: 58.333333333333336%; + } + .col-md-8 { + width: 66.66666666666666%; + } + .col-md-9 { + width: 75%; + } + .col-md-10 { + width: 83.33333333333334%; + } + .col-md-11 { + width: 91.66666666666666%; + } + .col-md-12 { + width: 100%; + } + .col-md-push-0 { + left: auto; + } + .col-md-push-1 { + left: 8.333333333333332%; + } + .col-md-push-2 { + left: 16.666666666666664%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-4 { + left: 33.33333333333333%; + } + .col-md-push-5 { + left: 41.66666666666667%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-7 { + left: 58.333333333333336%; + } + .col-md-push-8 { + left: 66.66666666666666%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-10 { + left: 83.33333333333334%; + } + .col-md-push-11 { + left: 91.66666666666666%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-pull-1 { + right: 8.333333333333332%; + } + .col-md-pull-2 { + right: 16.666666666666664%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-4 { + right: 33.33333333333333%; + } + .col-md-pull-5 { + right: 41.66666666666667%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-7 { + right: 58.333333333333336%; + } + .col-md-pull-8 { + right: 66.66666666666666%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-10 { + right: 83.33333333333334%; + } + .col-md-pull-11 { + right: 91.66666666666666%; + } + .col-md-offset-0 { + margin-left: 0; + } + .col-md-offset-1 { + margin-left: 8.333333333333332%; + } + .col-md-offset-2 { + margin-left: 16.666666666666664%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-4 { + margin-left: 33.33333333333333%; + } + .col-md-offset-5 { + margin-left: 41.66666666666667%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-7 { + margin-left: 58.333333333333336%; + } + .col-md-offset-8 { + margin-left: 66.66666666666666%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-10 { + margin-left: 83.33333333333334%; + } + .col-md-offset-11 { + margin-left: 91.66666666666666%; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1170px; + } + .col-lg-1, + .col-lg-2, + .col-lg-3, + .col-lg-4, + .col-lg-5, + .col-lg-6, + .col-lg-7, + .col-lg-8, + .col-lg-9, + .col-lg-10, + .col-lg-11 { + float: left; + } + .col-lg-1 { + width: 8.333333333333332%; + } + .col-lg-2 { + width: 16.666666666666664%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-4 { + width: 33.33333333333333%; + } + .col-lg-5 { + width: 41.66666666666667%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-7 { + width: 58.333333333333336%; + } + .col-lg-8 { + width: 66.66666666666666%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-10 { + width: 83.33333333333334%; + } + .col-lg-11 { + width: 91.66666666666666%; + } + .col-lg-12 { + width: 100%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-push-1 { + left: 8.333333333333332%; + } + .col-lg-push-2 { + left: 16.666666666666664%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-4 { + left: 33.33333333333333%; + } + .col-lg-push-5 { + left: 41.66666666666667%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-7 { + left: 58.333333333333336%; + } + .col-lg-push-8 { + left: 66.66666666666666%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-10 { + left: 83.33333333333334%; + } + .col-lg-push-11 { + left: 91.66666666666666%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-pull-1 { + right: 8.333333333333332%; + } + .col-lg-pull-2 { + right: 16.666666666666664%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-4 { + right: 33.33333333333333%; + } + .col-lg-pull-5 { + right: 41.66666666666667%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-7 { + right: 58.333333333333336%; + } + .col-lg-pull-8 { + right: 66.66666666666666%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-10 { + right: 83.33333333333334%; + } + .col-lg-pull-11 { + right: 91.66666666666666%; + } + .col-lg-offset-0 { + margin-left: 0; + } + .col-lg-offset-1 { + margin-left: 8.333333333333332%; + } + .col-lg-offset-2 { + margin-left: 16.666666666666664%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-4 { + margin-left: 33.33333333333333%; + } + .col-lg-offset-5 { + margin-left: 41.66666666666667%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-7 { + margin-left: 58.333333333333336%; + } + .col-lg-offset-8 { + margin-left: 66.66666666666666%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-10 { + margin-left: 83.33333333333334%; + } + .col-lg-offset-11 { + margin-left: 91.66666666666666%; + } +} + +table { + max-width: 100%; + background-color: transparent; +} + +th { + text-align: left; +} + +.table { + width: 100%; + margin-bottom: 20px; +} + +.table thead > tr > th, +.table tbody > tr > th, +.table tfoot > tr > th, +.table thead > tr > td, +.table tbody > tr > td, +.table tfoot > tr > td { + padding: 8px; + line-height: 1.428571429; + vertical-align: top; + border-top: 1px solid #dddddd; +} + +.table thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; +} + +.table caption + thead tr:first-child th, +.table colgroup + thead tr:first-child th, +.table thead:first-child tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child td { + border-top: 0; +} + +.table tbody + tbody { + border-top: 2px solid #dddddd; +} + +.table .table { + background-color: #ffffff; +} + +.table-condensed thead > tr > th, +.table-condensed tbody > tr > th, +.table-condensed tfoot > tr > th, +.table-condensed thead > tr > td, +.table-condensed tbody > tr > td, +.table-condensed tfoot > tr > td { + padding: 5px; +} + +.table-bordered { + border: 1px solid #dddddd; +} + +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; +} + +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} + +.table-striped > tbody > tr:nth-child(odd) > td, +.table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} + +.table-hover > tbody > tr:hover > td, +.table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} + +table col[class*="col-"] { + display: table-column; + float: none; +} + +table td[class*="col-"], +table th[class*="col-"] { + display: table-cell; + float: none; +} + +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} + +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td { + background-color: #d0e9c6; + border-color: #c9e2b3; +} + +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; + border-color: #eed3d7; +} + +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td { + background-color: #ebcccc; + border-color: #e6c1c7; +} + +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; + border-color: #fbeed5; +} + +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td { + background-color: #faf2cc; + border-color: #f8e5be; +} + +@media (max-width: 768px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-x: scroll; + overflow-y: hidden; + border: 1px solid #dddddd; + } + .table-responsive > .table { + margin-bottom: 0; + background-color: #fff; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > thead > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > thead > tr:last-child > td, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +label { + display: inline-block; + margin-bottom: 5px; + font-weight: bold; +} + +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + /* IE8-9 */ + + line-height: normal; +} + +input[type="file"] { + display: block; +} + +select[multiple], +select[size] { + height: auto; +} + +select optgroup { + font-family: inherit; + font-size: inherit; + font-style: inherit; +} + +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +input[type="number"]::-webkit-outer-spin-button, +input[type="number"]::-webkit-inner-spin-button { + height: auto; +} + +.form-control:-moz-placeholder { + color: #999999; +} + +.form-control::-moz-placeholder { + color: #999999; +} + +.form-control:-ms-input-placeholder { + color: #999999; +} + +.form-control::-webkit-input-placeholder { + color: #999999; +} + +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + color: #555555; + vertical-align: middle; + background-color: #ffffff; + border: 1px solid #cccccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; +} + +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); +} + +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; +} + +textarea.form-control { + height: auto; +} + +.form-group { + margin-bottom: 15px; +} + +.radio, +.checkbox { + display: block; + min-height: 20px; + padding-left: 20px; + margin-top: 10px; + margin-bottom: 10px; + vertical-align: middle; +} + +.radio label, +.checkbox label { + display: inline; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} + +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + float: left; + margin-left: -20px; +} + +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} + +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} + +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +.radio[disabled], +.radio-inline[disabled], +.checkbox[disabled], +.checkbox-inline[disabled], +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"], +fieldset[disabled] .radio, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} + +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +select.input-sm { + height: 30px; + line-height: 30px; +} + +textarea.input-sm { + height: auto; +} + +.input-lg { + height: 45px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +select.input-lg { + height: 45px; + line-height: 45px; +} + +textarea.input-lg { + height: auto; +} + +.has-warning .help-block, +.has-warning .control-label { + color: #c09853; +} + +.has-warning .form-control { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.has-warning .form-control:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; +} + +.has-warning .input-group-addon { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} + +.has-error .help-block, +.has-error .control-label { + color: #b94a48; +} + +.has-error .form-control { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.has-error .form-control:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} + +.has-error .input-group-addon { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} + +.has-success .help-block, +.has-success .control-label { + color: #468847; +} + +.has-success .form-control { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.has-success .form-control:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; +} + +.has-success .input-group-addon { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} + +.form-control-static { + padding-top: 7px; + margin-bottom: 0; +} + +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} + +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } +} + +.form-horizontal .control-label, +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} + +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} + +.form-horizontal .form-group:before, +.form-horizontal .form-group:after { + display: table; + content: " "; +} + +.form-horizontal .form-group:after { + clear: both; +} + +.form-horizontal .form-group:before, +.form-horizontal .form-group:after { + display: table; + content: " "; +} + +.form-horizontal .form-group:after { + clear: both; +} + +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + } +} + +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.428571429; + text-align: center; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + border: 1px solid transparent; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; +} + +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} + +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} + +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + color: #333333; + background-color: #ebebeb; + border-color: #adadad; +} + +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + background-image: none; +} + +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} + +.btn-primary { + color: #ffffff; + background-color: #428bca; + border-color: #357ebd; +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #3276b1; + border-color: #285e8e; +} + +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + background-image: none; +} + +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} + +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} + +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ed9c28; + border-color: #d58512; +} + +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + background-image: none; +} + +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} + +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} + +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #d2322d; + border-color: #ac2925; +} + +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + background-image: none; +} + +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} + +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} + +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #47a447; + border-color: #398439; +} + +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + background-image: none; +} + +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} + +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} + +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #39b3d7; + border-color: #269abc; +} + +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + background-image: none; +} + +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} + +.btn-link { + font-weight: normal; + color: #428bca; + cursor: pointer; + border-radius: 0; +} + +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} + +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} + +.btn-link:hover, +.btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} + +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #999999; + text-decoration: none; +} + +.btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +.btn-sm, +.btn-xs { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-xs { + padding: 1px 5px; +} + +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; +} + +.btn-block + .btn-block { + margin-top: 5px; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +.fade.in { + opacity: 1; +} + +.collapse { + display: none; +} + +.collapse.in { + display: block; +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg'); +} + +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + -webkit-font-smoothing: antialiased; + font-style: normal; + font-weight: normal; + line-height: 1; +} + +.glyphicon-asterisk:before { + content: "\2a"; +} + +.glyphicon-plus:before { + content: "\2b"; +} + +.glyphicon-euro:before { + content: "\20ac"; +} + +.glyphicon-minus:before { + content: "\2212"; +} + +.glyphicon-cloud:before { + content: "\2601"; +} + +.glyphicon-envelope:before { + content: "\2709"; +} + +.glyphicon-pencil:before { + content: "\270f"; +} + +.glyphicon-glass:before { + content: "\e001"; +} + +.glyphicon-music:before { + content: "\e002"; +} + +.glyphicon-search:before { + content: "\e003"; +} + +.glyphicon-heart:before { + content: "\e005"; +} + +.glyphicon-star:before { + content: "\e006"; +} + +.glyphicon-star-empty:before { + content: "\e007"; +} + +.glyphicon-user:before { + content: "\e008"; +} + +.glyphicon-film:before { + content: "\e009"; +} + +.glyphicon-th-large:before { + content: "\e010"; +} + +.glyphicon-th:before { + content: "\e011"; +} + +.glyphicon-th-list:before { + content: "\e012"; +} + +.glyphicon-ok:before { + content: "\e013"; +} + +.glyphicon-remove:before { + content: "\e014"; +} + +.glyphicon-zoom-in:before { + content: "\e015"; +} + +.glyphicon-zoom-out:before { + content: "\e016"; +} + +.glyphicon-off:before { + content: "\e017"; +} + +.glyphicon-signal:before { + content: "\e018"; +} + +.glyphicon-cog:before { + content: "\e019"; +} + +.glyphicon-trash:before { + content: "\e020"; +} + +.glyphicon-home:before { + content: "\e021"; +} + +.glyphicon-file:before { + content: "\e022"; +} + +.glyphicon-time:before { + content: "\e023"; +} + +.glyphicon-road:before { + content: "\e024"; +} + +.glyphicon-download-alt:before { + content: "\e025"; +} + +.glyphicon-download:before { + content: "\e026"; +} + +.glyphicon-upload:before { + content: "\e027"; +} + +.glyphicon-inbox:before { + content: "\e028"; +} + +.glyphicon-play-circle:before { + content: "\e029"; +} + +.glyphicon-repeat:before { + content: "\e030"; +} + +.glyphicon-refresh:before { + content: "\e031"; +} + +.glyphicon-list-alt:before { + content: "\e032"; +} + +.glyphicon-flag:before { + content: "\e034"; +} + +.glyphicon-headphones:before { + content: "\e035"; +} + +.glyphicon-volume-off:before { + content: "\e036"; +} + +.glyphicon-volume-down:before { + content: "\e037"; +} + +.glyphicon-volume-up:before { + content: "\e038"; +} + +.glyphicon-qrcode:before { + content: "\e039"; +} + +.glyphicon-barcode:before { + content: "\e040"; +} + +.glyphicon-tag:before { + content: "\e041"; +} + +.glyphicon-tags:before { + content: "\e042"; +} + +.glyphicon-book:before { + content: "\e043"; +} + +.glyphicon-print:before { + content: "\e045"; +} + +.glyphicon-font:before { + content: "\e047"; +} + +.glyphicon-bold:before { + content: "\e048"; +} + +.glyphicon-italic:before { + content: "\e049"; +} + +.glyphicon-text-height:before { + content: "\e050"; +} + +.glyphicon-text-width:before { + content: "\e051"; +} + +.glyphicon-align-left:before { + content: "\e052"; +} + +.glyphicon-align-center:before { + content: "\e053"; +} + +.glyphicon-align-right:before { + content: "\e054"; +} + +.glyphicon-align-justify:before { + content: "\e055"; +} + +.glyphicon-list:before { + content: "\e056"; +} + +.glyphicon-indent-left:before { + content: "\e057"; +} + +.glyphicon-indent-right:before { + content: "\e058"; +} + +.glyphicon-facetime-video:before { + content: "\e059"; +} + +.glyphicon-picture:before { + content: "\e060"; +} + +.glyphicon-map-marker:before { + content: "\e062"; +} + +.glyphicon-adjust:before { + content: "\e063"; +} + +.glyphicon-tint:before { + content: "\e064"; +} + +.glyphicon-edit:before { + content: "\e065"; +} + +.glyphicon-share:before { + content: "\e066"; +} + +.glyphicon-check:before { + content: "\e067"; +} + +.glyphicon-move:before { + content: "\e068"; +} + +.glyphicon-step-backward:before { + content: "\e069"; +} + +.glyphicon-fast-backward:before { + content: "\e070"; +} + +.glyphicon-backward:before { + content: "\e071"; +} + +.glyphicon-play:before { + content: "\e072"; +} + +.glyphicon-pause:before { + content: "\e073"; +} + +.glyphicon-stop:before { + content: "\e074"; +} + +.glyphicon-forward:before { + content: "\e075"; +} + +.glyphicon-fast-forward:before { + content: "\e076"; +} + +.glyphicon-step-forward:before { + content: "\e077"; +} + +.glyphicon-eject:before { + content: "\e078"; +} + +.glyphicon-chevron-left:before { + content: "\e079"; +} + +.glyphicon-chevron-right:before { + content: "\e080"; +} + +.glyphicon-plus-sign:before { + content: "\e081"; +} + +.glyphicon-minus-sign:before { + content: "\e082"; +} + +.glyphicon-remove-sign:before { + content: "\e083"; +} + +.glyphicon-ok-sign:before { + content: "\e084"; +} + +.glyphicon-question-sign:before { + content: "\e085"; +} + +.glyphicon-info-sign:before { + content: "\e086"; +} + +.glyphicon-screenshot:before { + content: "\e087"; +} + +.glyphicon-remove-circle:before { + content: "\e088"; +} + +.glyphicon-ok-circle:before { + content: "\e089"; +} + +.glyphicon-ban-circle:before { + content: "\e090"; +} + +.glyphicon-arrow-left:before { + content: "\e091"; +} + +.glyphicon-arrow-right:before { + content: "\e092"; +} + +.glyphicon-arrow-up:before { + content: "\e093"; +} + +.glyphicon-arrow-down:before { + content: "\e094"; +} + +.glyphicon-share-alt:before { + content: "\e095"; +} + +.glyphicon-resize-full:before { + content: "\e096"; +} + +.glyphicon-resize-small:before { + content: "\e097"; +} + +.glyphicon-exclamation-sign:before { + content: "\e101"; +} + +.glyphicon-gift:before { + content: "\e102"; +} + +.glyphicon-leaf:before { + content: "\e103"; +} + +.glyphicon-eye-open:before { + content: "\e105"; +} + +.glyphicon-eye-close:before { + content: "\e106"; +} + +.glyphicon-warning-sign:before { + content: "\e107"; +} + +.glyphicon-plane:before { + content: "\e108"; +} + +.glyphicon-random:before { + content: "\e110"; +} + +.glyphicon-comment:before { + content: "\e111"; +} + +.glyphicon-magnet:before { + content: "\e112"; +} + +.glyphicon-chevron-up:before { + content: "\e113"; +} + +.glyphicon-chevron-down:before { + content: "\e114"; +} + +.glyphicon-retweet:before { + content: "\e115"; +} + +.glyphicon-shopping-cart:before { + content: "\e116"; +} + +.glyphicon-folder-close:before { + content: "\e117"; +} + +.glyphicon-folder-open:before { + content: "\e118"; +} + +.glyphicon-resize-vertical:before { + content: "\e119"; +} + +.glyphicon-resize-horizontal:before { + content: "\e120"; +} + +.glyphicon-hdd:before { + content: "\e121"; +} + +.glyphicon-bullhorn:before { + content: "\e122"; +} + +.glyphicon-certificate:before { + content: "\e124"; +} + +.glyphicon-thumbs-up:before { + content: "\e125"; +} + +.glyphicon-thumbs-down:before { + content: "\e126"; +} + +.glyphicon-hand-right:before { + content: "\e127"; +} + +.glyphicon-hand-left:before { + content: "\e128"; +} + +.glyphicon-hand-up:before { + content: "\e129"; +} + +.glyphicon-hand-down:before { + content: "\e130"; +} + +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} + +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} + +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} + +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} + +.glyphicon-globe:before { + content: "\e135"; +} + +.glyphicon-tasks:before { + content: "\e137"; +} + +.glyphicon-filter:before { + content: "\e138"; +} + +.glyphicon-fullscreen:before { + content: "\e140"; +} + +.glyphicon-dashboard:before { + content: "\e141"; +} + +.glyphicon-heart-empty:before { + content: "\e143"; +} + +.glyphicon-link:before { + content: "\e144"; +} + +.glyphicon-phone:before { + content: "\e145"; +} + +.glyphicon-usd:before { + content: "\e148"; +} + +.glyphicon-gbp:before { + content: "\e149"; +} + +.glyphicon-sort:before { + content: "\e150"; +} + +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} + +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} + +.glyphicon-sort-by-order:before { + content: "\e153"; +} + +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} + +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} + +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} + +.glyphicon-unchecked:before { + content: "\e157"; +} + +.glyphicon-expand:before { + content: "\e158"; +} + +.glyphicon-collapse-down:before { + content: "\e159"; +} + +.glyphicon-collapse-up:before { + content: "\e160"; +} + +.glyphicon-log-in:before { + content: "\e161"; +} + +.glyphicon-flash:before { + content: "\e162"; +} + +.glyphicon-log-out:before { + content: "\e163"; +} + +.glyphicon-new-window:before { + content: "\e164"; +} + +.glyphicon-record:before { + content: "\e165"; +} + +.glyphicon-save:before { + content: "\e166"; +} + +.glyphicon-open:before { + content: "\e167"; +} + +.glyphicon-saved:before { + content: "\e168"; +} + +.glyphicon-import:before { + content: "\e169"; +} + +.glyphicon-export:before { + content: "\e170"; +} + +.glyphicon-send:before { + content: "\e171"; +} + +.glyphicon-floppy-disk:before { + content: "\e172"; +} + +.glyphicon-floppy-saved:before { + content: "\e173"; +} + +.glyphicon-floppy-remove:before { + content: "\e174"; +} + +.glyphicon-floppy-save:before { + content: "\e175"; +} + +.glyphicon-floppy-open:before { + content: "\e176"; +} + +.glyphicon-credit-card:before { + content: "\e177"; +} + +.glyphicon-transfer:before { + content: "\e178"; +} + +.glyphicon-cutlery:before { + content: "\e179"; +} + +.glyphicon-header:before { + content: "\e180"; +} + +.glyphicon-compressed:before { + content: "\e181"; +} + +.glyphicon-earphone:before { + content: "\e182"; +} + +.glyphicon-phone-alt:before { + content: "\e183"; +} + +.glyphicon-tower:before { + content: "\e184"; +} + +.glyphicon-stats:before { + content: "\e185"; +} + +.glyphicon-sd-video:before { + content: "\e186"; +} + +.glyphicon-hd-video:before { + content: "\e187"; +} + +.glyphicon-subtitles:before { + content: "\e188"; +} + +.glyphicon-sound-stereo:before { + content: "\e189"; +} + +.glyphicon-sound-dolby:before { + content: "\e190"; +} + +.glyphicon-sound-5-1:before { + content: "\e191"; +} + +.glyphicon-sound-6-1:before { + content: "\e192"; +} + +.glyphicon-sound-7-1:before { + content: "\e193"; +} + +.glyphicon-copyright-mark:before { + content: "\e194"; +} + +.glyphicon-registration-mark:before { + content: "\e195"; +} + +.glyphicon-cloud-download:before { + content: "\e197"; +} + +.glyphicon-cloud-upload:before { + content: "\e198"; +} + +.glyphicon-tree-conifer:before { + content: "\e199"; +} + +.glyphicon-tree-deciduous:before { + content: "\e200"; +} + +.glyphicon-briefcase:before { + content: "\1f4bc"; +} + +.glyphicon-calendar:before { + content: "\1f4c5"; +} + +.glyphicon-pushpin:before { + content: "\1f4cc"; +} + +.glyphicon-paperclip:before { + content: "\1f4ce"; +} + +.glyphicon-camera:before { + content: "\1f4f7"; +} + +.glyphicon-lock:before { + content: "\1f512"; +} + +.glyphicon-bell:before { + content: "\1f514"; +} + +.glyphicon-bookmark:before { + content: "\1f516"; +} + +.glyphicon-fire:before { + content: "\1f525"; +} + +.glyphicon-wrench:before { + content: "\1f527"; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-bottom: 0 dotted; + border-left: 4px solid transparent; + content: ""; +} + +.dropdown { + position: relative; +} + +.dropdown-toggle:focus { + outline: 0; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + list-style: none; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} + +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #428bca; +} + +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #428bca; + outline: 0; +} + +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} + +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.open > .dropdown-menu { + display: block; +} + +.open > a { + outline: 0; +} + +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.428571429; + color: #999999; +} + +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0 dotted; + border-bottom: 4px solid #000000; + content: ""; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } +} + +.btn-default .caret { + border-top-color: #333333; +} + +.btn-primary .caret, +.btn-success .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret { + border-top-color: #fff; +} + +.dropup .btn-default .caret { + border-bottom-color: #333333; +} + +.dropup .btn-primary .caret, +.dropup .btn-success .caret, +.dropup .btn-warning .caret, +.dropup .btn-danger .caret, +.dropup .btn-info .caret { + border-bottom-color: #fff; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} + +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} + +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} + +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus { + outline: none; +} + +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} + +.btn-toolbar:before, +.btn-toolbar:after { + display: table; + content: " "; +} + +.btn-toolbar:after { + clear: both; +} + +.btn-toolbar:before, +.btn-toolbar:after { + display: table; + content: " "; +} + +.btn-toolbar:after { + clear: both; +} + +.btn-toolbar .btn-group { + float: left; +} + +.btn-toolbar > .btn + .btn, +.btn-toolbar > .btn-group + .btn, +.btn-toolbar > .btn + .btn-group, +.btn-toolbar > .btn-group + .btn-group { + margin-left: 5px; +} + +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} + +.btn-group > .btn:first-child { + margin-left: 0; +} + +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.btn-group > .btn-group { + float: left; +} + +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} + +.btn-group > .btn-group:first-child > .btn:last-child, +.btn-group > .btn-group:first-child > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group > .btn-group:last-child > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group-xs > .btn { + padding: 5px 10px; + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} + +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} + +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + +.btn .caret { + margin-left: 0; +} + +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} + +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} + +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + display: block; + float: none; + width: 100%; + max-width: 100%; +} + +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after { + display: table; + content: " "; +} + +.btn-group-vertical > .btn-group:after { + clear: both; +} + +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after { + display: table; + content: " "; +} + +.btn-group-vertical > .btn-group:after { + clear: both; +} + +.btn-group-vertical > .btn-group > .btn { + float: none; +} + +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} + +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-right-radius: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 0; +} + +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} + +.btn-group-vertical > .btn-group:first-child > .btn:last-child, +.btn-group-vertical > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-group-vertical > .btn-group:last-child > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.btn-group-justified { + display: table; + width: 100%; + border-collapse: separate; + table-layout: fixed; +} + +.btn-group-justified .btn { + display: table-cell; + float: none; + width: 1%; +} + +[data-toggle="buttons"] > .btn > input[type="radio"], +[data-toggle="buttons"] > .btn > input[type="checkbox"] { + display: none; +} + +.input-group { + position: relative; + display: table; + border-collapse: separate; +} + +.input-group.col { + float: none; + padding-right: 0; + padding-left: 0; +} + +.input-group .form-control { + width: 100%; + margin-bottom: 0; +} + +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 45px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 45px; + line-height: 45px; +} + +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn { + height: auto; +} + +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} + +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn { + height: auto; +} + +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} + +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} + +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} + +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + text-align: center; + background-color: #eeeeee; + border: 1px solid #cccccc; + border-radius: 4px; +} + +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} + +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} + +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} + +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group-addon:first-child { + border-right: 0; +} + +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.input-group-addon:last-child { + border-left: 0; +} + +.input-group-btn { + position: relative; + white-space: nowrap; +} + +.input-group-btn > .btn { + position: relative; +} + +.input-group-btn > .btn + .btn { + margin-left: -4px; +} + +.input-group-btn > .btn:hover, +.input-group-btn > .btn:active { + z-index: 2; +} + +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav:before, +.nav:after { + display: table; + content: " "; +} + +.nav:after { + clear: both; +} + +.nav:before, +.nav:after { + display: table; + content: " "; +} + +.nav:after { + clear: both; +} + +.nav > li { + position: relative; + display: block; +} + +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} + +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} + +.nav > li.disabled > a { + color: #999999; +} + +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #999999; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} + +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eeeeee; + border-color: #428bca; +} + +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} + +.nav > li > a > img { + max-width: none; +} + +.nav-tabs { + border-bottom: 1px solid #dddddd; +} + +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} + +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.428571429; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} + +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + cursor: default; + background-color: #ffffff; + border: 1px solid #dddddd; + border-bottom-color: transparent; +} + +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} + +.nav-tabs.nav-justified > li { + float: none; +} + +.nav-tabs.nav-justified > li > a { + text-align: center; +} + +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } +} + +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-bottom: 1px solid #dddddd; +} + +.nav-tabs.nav-justified > .active > a { + border-bottom-color: #ffffff; +} + +.nav-pills > li { + float: left; +} + +.nav-pills > li > a { + border-radius: 5px; +} + +.nav-pills > li + li { + margin-left: 2px; +} + +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #428bca; +} + +.nav-stacked > li { + float: none; +} + +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} + +.nav-justified { + width: 100%; +} + +.nav-justified > li { + float: none; +} + +.nav-justified > li > a { + text-align: center; +} + +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } +} + +.nav-tabs-justified { + border-bottom: 0; +} + +.nav-tabs-justified > li > a { + margin-right: 0; + border-bottom: 1px solid #dddddd; +} + +.nav-tabs-justified > .active > a { + border-bottom-color: #ffffff; +} + +.tabbable:before, +.tabbable:after { + display: table; + content: " "; +} + +.tabbable:after { + clear: both; +} + +.tabbable:before, +.tabbable:after { + display: table; + content: " "; +} + +.tabbable:after { + clear: both; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.nav .caret { + border-top-color: #428bca; + border-bottom-color: #428bca; +} + +.nav a:hover .caret { + border-top-color: #2a6496; + border-bottom-color: #2a6496; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.navbar { + position: relative; + z-index: 1000; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} + +.navbar:before, +.navbar:after { + display: table; + content: " "; +} + +.navbar:after { + clear: both; +} + +.navbar:before, +.navbar:after { + display: table; + content: " "; +} + +.navbar:after { + clear: both; +} + +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} + +.navbar-header:before, +.navbar-header:after { + display: table; + content: " "; +} + +.navbar-header:after { + clear: both; +} + +.navbar-header:before, +.navbar-header:after { + display: table; + content: " "; +} + +.navbar-header:after { + clear: both; +} + +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} + +.navbar-collapse { + max-height: 340px; + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} + +.navbar-collapse:before, +.navbar-collapse:after { + display: table; + content: " "; +} + +.navbar-collapse:after { + clear: both; +} + +.navbar-collapse:before, +.navbar-collapse:after { + display: table; + content: " "; +} + +.navbar-collapse:after { + clear: both; +} + +.navbar-collapse.in { + overflow-y: auto; +} + +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-collapse .navbar-nav.navbar-left:first-child { + margin-left: -15px; + } + .navbar-collapse .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } + .navbar-collapse .navbar-text:last-child { + margin-right: 0; + } +} + +.container > .navbar-header, +.container > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} + +@media (min-width: 768px) { + .container > .navbar-header, + .container > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} + +.navbar-static-top { + border-width: 0 0 1px; +} + +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + border-width: 0 0 1px; +} + +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} + +.navbar-fixed-top { + top: 0; + z-index: 1030; +} + +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; +} + +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} + +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} + +@media (min-width: 768px) { + .navbar > .container .navbar-brand { + margin-left: -15px; + } +} + +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + border: 1px solid transparent; + border-radius: 4px; +} + +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} + +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} + +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} + +.navbar-nav { + margin: 7.5px -15px; +} + +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} + +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} + +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} + +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + } +} + +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); +} + +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } +} + +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } +} + +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} + +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.navbar-nav.pull-right > li > .dropdown-menu, +.navbar-nav > li > .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} + +.navbar-text { + float: left; + margin-top: 15px; + margin-bottom: 15px; +} + +@media (min-width: 768px) { + .navbar-text { + margin-right: 15px; + margin-left: 15px; + } +} + +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} + +.navbar-default .navbar-brand { + color: #777777; +} + +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} + +.navbar-default .navbar-text { + color: #777777; +} + +.navbar-default .navbar-nav > li > a { + color: #777777; +} + +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333333; + background-color: transparent; +} + +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555555; + background-color: #e7e7e7; +} + +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} + +.navbar-default .navbar-toggle { + border-color: #dddddd; +} + +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #dddddd; +} + +.navbar-default .navbar-toggle .icon-bar { + background-color: #cccccc; +} + +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e6e6e6; +} + +.navbar-default .navbar-nav > .dropdown > a:hover .caret, +.navbar-default .navbar-nav > .dropdown > a:focus .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} + +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555555; + background-color: #e7e7e7; +} + +.navbar-default .navbar-nav > .open > a .caret, +.navbar-default .navbar-nav > .open > a:hover .caret, +.navbar-default .navbar-nav > .open > a:focus .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.navbar-default .navbar-nav > .dropdown > a .caret { + border-top-color: #777777; + border-bottom-color: #777777; +} + +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} + +.navbar-default .navbar-link { + color: #777777; +} + +.navbar-default .navbar-link:hover { + color: #333333; +} + +.navbar-inverse { + background-color: #222222; + border-color: #080808; +} + +.navbar-inverse .navbar-brand { + color: #999999; +} + +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .navbar-text { + color: #999999; +} + +.navbar-inverse .navbar-nav > li > a { + color: #999999; +} + +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; +} + +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; +} + +.navbar-inverse .navbar-toggle { + border-color: #333333; +} + +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333333; +} + +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} + +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} + +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #ffffff; + background-color: #080808; +} + +.navbar-inverse .navbar-nav > .dropdown > a:hover .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .navbar-nav > .dropdown > a .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} + +.navbar-inverse .navbar-nav > .open > a .caret, +.navbar-inverse .navbar-nav > .open > a:hover .caret, +.navbar-inverse .navbar-nav > .open > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #999999; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} + +.navbar-inverse .navbar-link { + color: #999999; +} + +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} + +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} + +.breadcrumb > li { + display: inline-block; +} + +.breadcrumb > li + li:before { + padding: 0 5px; + color: #cccccc; + content: "/\00a0"; +} + +.breadcrumb > .active { + color: #999999; +} + +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} + +.pagination > li { + display: inline; +} + +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.428571429; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; +} + +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} + +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + background-color: #eeeeee; +} + +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + cursor: default; + background-color: #428bca; + border-color: #428bca; +} + +.pagination > .disabled > span, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #999999; + cursor: not-allowed; + background-color: #ffffff; + border-color: #dddddd; +} + +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} + +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} + +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} + +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} + +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} + +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} + +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} + +.pager:before, +.pager:after { + display: table; + content: " "; +} + +.pager:after { + clear: both; +} + +.pager:before, +.pager:after { + display: table; + content: " "; +} + +.pager:after { + clear: both; +} + +.pager li { + display: inline; +} + +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 15px; +} + +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} + +.pager .next > a, +.pager .next > span { + float: right; +} + +.pager .previous > a, +.pager .previous > span { + float: left; +} + +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + cursor: not-allowed; + background-color: #ffffff; +} + +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} + +.label[href]:hover, +.label[href]:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label:empty { + display: none; +} + +.label-default { + background-color: #999999; +} + +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #808080; +} + +.label-primary { + background-color: #428bca; +} + +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #3071a9; +} + +.label-success { + background-color: #5cb85c; +} + +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} + +.label-info { + background-color: #5bc0de; +} + +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} + +.label-warning { + background-color: #f0ad4e; +} + +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} + +.label-danger { + background-color: #d9534f; +} + +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} + +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; + border-radius: 10px; +} + +.badge:empty { + display: none; +} + +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.btn .badge { + position: relative; + top: -1px; +} + +a.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #428bca; + background-color: #ffffff; +} + +.nav-pills > li > a > .badge { + margin-left: 3px; +} + +.jumbotron { + padding: 30px; + margin-bottom: 30px; + font-size: 21px; + font-weight: 200; + line-height: 2.1428571435; + color: inherit; + background-color: #eeeeee; +} + +.jumbotron h1 { + line-height: 1; + color: inherit; +} + +.jumbotron p { + line-height: 1.4; +} + +.container .jumbotron { + border-radius: 6px; +} + +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1 { + font-size: 63px; + } +} + +.thumbnail { + display: inline-block; + display: block; + height: auto; + max-width: 100%; + padding: 4px; + line-height: 1.428571429; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +.thumbnail > img { + display: block; + height: auto; + max-width: 100%; +} + +a.thumbnail:hover, +a.thumbnail:focus { + border-color: #428bca; +} + +.thumbnail > img { + margin-right: auto; + margin-left: auto; +} + +.thumbnail .caption { + padding: 9px; + color: #333333; +} + +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} + +.alert h4 { + margin-top: 0; + color: inherit; +} + +.alert .alert-link { + font-weight: bold; +} + +.alert > p, +.alert > ul { + margin-bottom: 0; +} + +.alert > p + p { + margin-top: 5px; +} + +.alert-dismissable { + padding-right: 35px; +} + +.alert-dismissable .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.alert-success hr { + border-top-color: #c9e2b3; +} + +.alert-success .alert-link { + color: #356635; +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.alert-info hr { + border-top-color: #a6e1ec; +} + +.alert-info .alert-link { + color: #2d6987; +} + +.alert-warning { + color: #c09853; + background-color: #fcf8e3; + border-color: #fbeed5; +} + +.alert-warning hr { + border-top-color: #f8e5be; +} + +.alert-warning .alert-link { + color: #a47e3c; +} + +.alert-danger { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.alert-danger hr { + border-top-color: #e6c1c7; +} + +.alert-danger .alert-link { + color: #953b39; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + color: #ffffff; + text-align: center; + background-color: #428bca; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress-striped .progress-bar { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} + +.progress.active .progress-bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-bar-success { + background-color: #5cb85c; +} + +.progress-striped .progress-bar-success { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-info { + background-color: #5bc0de; +} + +.progress-striped .progress-bar-info { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-warning { + background-color: #f0ad4e; +} + +.progress-striped .progress-bar-warning { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-danger { + background-color: #d9534f; +} + +.progress-striped .progress-bar-danger { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.media, +.media-body { + overflow: hidden; + zoom: 1; +} + +.media, +.media .media { + margin-top: 15px; +} + +.media:first-child { + margin-top: 0; +} + +.media-object { + display: block; +} + +.media-heading { + margin: 0 0 5px; +} + +.media > .pull-left { + margin-right: 10px; +} + +.media > .pull-right { + margin-left: 10px; +} + +.media-list { + padding-left: 0; + list-style: none; +} + +.list-group { + padding-left: 0; + margin-bottom: 20px; +} + +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} + +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} + +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} + +.list-group-item > .badge { + float: right; +} + +.list-group-item > .badge + .badge { + margin-right: 5px; +} + +a.list-group-item { + color: #555555; +} + +a.list-group-item .list-group-item-heading { + color: #333333; +} + +a.list-group-item:hover, +a.list-group-item:focus { + text-decoration: none; + background-color: #f5f5f5; +} + +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #428bca; + border-color: #428bca; +} + +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading { + color: inherit; +} + +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #e1edf7; +} + +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} + +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} + +.panel { + margin-bottom: 20px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.panel-body { + padding: 15px; +} + +.panel-body:before, +.panel-body:after { + display: table; + content: " "; +} + +.panel-body:after { + clear: both; +} + +.panel-body:before, +.panel-body:after { + display: table; + content: " "; +} + +.panel-body:after { + clear: both; +} + +.panel > .list-group { + margin-bottom: 0; +} + +.panel > .list-group .list-group-item { + border-width: 1px 0; +} + +.panel > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.panel > .list-group .list-group-item:last-child { + border-bottom: 0; +} + +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} + +.panel > .table { + margin-bottom: 0; +} + +.panel > .panel-body + .table { + border-top: 1px solid #dddddd; +} + +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} + +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; +} + +.panel-title > a { + color: inherit; +} + +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +.panel-group .panel { + margin-bottom: 0; + overflow: hidden; + border-radius: 4px; +} + +.panel-group .panel + .panel { + margin-top: 5px; +} + +.panel-group .panel-heading { + border-bottom: 0; +} + +.panel-group .panel-heading + .panel-collapse .panel-body { + border-top: 1px solid #dddddd; +} + +.panel-group .panel-footer { + border-top: 0; +} + +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; +} + +.panel-default { + border-color: #dddddd; +} + +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; +} + +.panel-default > .panel-heading + .panel-collapse .panel-body { + border-top-color: #dddddd; +} + +.panel-default > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #dddddd; +} + +.panel-primary { + border-color: #428bca; +} + +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #428bca; + border-color: #428bca; +} + +.panel-primary > .panel-heading + .panel-collapse .panel-body { + border-top-color: #428bca; +} + +.panel-primary > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #428bca; +} + +.panel-success { + border-color: #d6e9c6; +} + +.panel-success > .panel-heading { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.panel-success > .panel-heading + .panel-collapse .panel-body { + border-top-color: #d6e9c6; +} + +.panel-success > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #d6e9c6; +} + +.panel-warning { + border-color: #fbeed5; +} + +.panel-warning > .panel-heading { + color: #c09853; + background-color: #fcf8e3; + border-color: #fbeed5; +} + +.panel-warning > .panel-heading + .panel-collapse .panel-body { + border-top-color: #fbeed5; +} + +.panel-warning > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #fbeed5; +} + +.panel-danger { + border-color: #eed3d7; +} + +.panel-danger > .panel-heading { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.panel-danger > .panel-heading + .panel-collapse .panel-body { + border-top-color: #eed3d7; +} + +.panel-danger > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #eed3d7; +} + +.panel-info { + border-color: #bce8f1; +} + +.panel-info > .panel-heading { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.panel-info > .panel-heading + .panel-collapse .panel-body { + border-top-color: #bce8f1; +} + +.panel-info > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #bce8f1; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +.well-lg { + padding: 24px; + border-radius: 6px; +} + +.well-sm { + padding: 9px; + border-radius: 3px; +} + +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.modal-open { + overflow: hidden; +} + +body.modal-open, +.modal-open .navbar-fixed-top, +.modal-open .navbar-fixed-bottom { + margin-right: 15px; +} + +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + display: none; + overflow: auto; + overflow-y: scroll; +} + +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} + +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0); +} + +.modal-dialog { + z-index: 1050; + width: auto; + padding: 10px; + margin-right: auto; + margin-left: auto; +} + +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; + background-color: #000000; +} + +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} + +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} + +.modal-header { + min-height: 16.428571429px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} + +.modal-header .close { + margin-top: -2px; +} + +.modal-title { + margin: 0; + line-height: 1.428571429; +} + +.modal-body { + position: relative; + padding: 20px; +} + +.modal-footer { + padding: 19px 20px 20px; + margin-top: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} + +@media screen and (min-width: 768px) { + .modal-dialog { + right: auto; + left: 50%; + width: 600px; + padding-top: 30px; + padding-bottom: 30px; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 12px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} + +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} + +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} + +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} + +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} + +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.top-right .tooltip-arrow { + right: 5px; + bottom: 0; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000000; + border-width: 5px 5px 5px 0; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000000; + border-width: 5px 0 5px 5px; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + background-clip: padding-box; +} + +.popover.top { + margin-top: -10px; +} + +.popover.right { + margin-left: 10px; +} + +.popover.bottom { + margin-top: 10px; +} + +.popover.left { + margin-left: -10px; +} + +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} + +.popover-content { + padding: 9px 14px; +} + +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover .arrow { + border-width: 11px; +} + +.popover .arrow:after { + border-width: 10px; + content: ""; +} + +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + border-bottom-width: 0; +} + +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-top-color: #ffffff; + border-bottom-width: 0; + content: " "; +} + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); + border-left-width: 0; +} + +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + border-right-color: #ffffff; + border-left-width: 0; + content: " "; +} + +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-top-width: 0; +} + +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-bottom-color: #ffffff; + border-top-width: 0; + content: " "; +} + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); + border-right-width: 0; +} + +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + border-left-color: #ffffff; + border-right-width: 0; + content: " "; +} + +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} + +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + height: auto; + max-width: 100%; + line-height: 1; +} + +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} + +.carousel-inner > .active { + left: 0; +} + +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel-inner > .next { + left: 100%; +} + +.carousel-inner > .prev { + left: -100%; +} + +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} + +.carousel-inner > .active.left { + left: -100%; +} + +.carousel-inner > .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); + opacity: 0.5; + filter: alpha(opacity=50); +} + +.carousel-control.left { + background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(rgba(0, 0, 0, 0.0001) 100%)); + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} + +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(rgba(0, 0, 0, 0.5) 100%)); + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} + +.carousel-control:hover, +.carousel-control:focus { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} + +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + left: 50%; + z-index: 5; + display: inline-block; +} + +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + font-family: serif; +} + +.carousel-control .icon-prev:before { + content: '\2039'; +} + +.carousel-control .icon-next:before { + content: '\203a'; +} + +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} + +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + border: 1px solid #ffffff; + border-radius: 10px; +} + +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #ffffff; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} + +.carousel-caption .btn { + text-shadow: none; +} + +@media screen and (min-width: 768px) { + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + margin-left: -15px; + font-size: 30px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} + +.clearfix:before, +.clearfix:after { + display: table; + content: " "; +} + +.clearfix:after { + clear: both; +} + +.pull-right { + float: right !important; +} + +.pull-left { + float: left !important; +} + +.hide { + display: none !important; +} + +.show { + display: block !important; +} + +.invisible { + visibility: hidden; +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.affix { + position: fixed; +} + +@-ms-viewport { + width: device-width; +} + +@media screen and (max-width: 400px) { + @-ms-viewport { + width: 320px; + } +} + +.hidden { + display: none !important; + visibility: hidden !important; +} + +.visible-xs { + display: none !important; +} + +tr.visible-xs { + display: none !important; +} + +th.visible-xs, +td.visible-xs { + display: none !important; +} + +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-xs.visible-sm { + display: block !important; + } + tr.visible-xs.visible-sm { + display: table-row !important; + } + th.visible-xs.visible-sm, + td.visible-xs.visible-sm { + display: table-cell !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-xs.visible-md { + display: block !important; + } + tr.visible-xs.visible-md { + display: table-row !important; + } + th.visible-xs.visible-md, + td.visible-xs.visible-md { + display: table-cell !important; + } +} + +@media (min-width: 1200px) { + .visible-xs.visible-lg { + display: block !important; + } + tr.visible-xs.visible-lg { + display: table-row !important; + } + th.visible-xs.visible-lg, + td.visible-xs.visible-lg { + display: table-cell !important; + } +} + +.visible-sm { + display: none !important; +} + +tr.visible-sm { + display: none !important; +} + +th.visible-sm, +td.visible-sm { + display: none !important; +} + +@media (max-width: 767px) { + .visible-sm.visible-xs { + display: block !important; + } + tr.visible-sm.visible-xs { + display: table-row !important; + } + th.visible-sm.visible-xs, + td.visible-sm.visible-xs { + display: table-cell !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-sm.visible-md { + display: block !important; + } + tr.visible-sm.visible-md { + display: table-row !important; + } + th.visible-sm.visible-md, + td.visible-sm.visible-md { + display: table-cell !important; + } +} + +@media (min-width: 1200px) { + .visible-sm.visible-lg { + display: block !important; + } + tr.visible-sm.visible-lg { + display: table-row !important; + } + th.visible-sm.visible-lg, + td.visible-sm.visible-lg { + display: table-cell !important; + } +} + +.visible-md { + display: none !important; +} + +tr.visible-md { + display: none !important; +} + +th.visible-md, +td.visible-md { + display: none !important; +} + +@media (max-width: 767px) { + .visible-md.visible-xs { + display: block !important; + } + tr.visible-md.visible-xs { + display: table-row !important; + } + th.visible-md.visible-xs, + td.visible-md.visible-xs { + display: table-cell !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-md.visible-sm { + display: block !important; + } + tr.visible-md.visible-sm { + display: table-row !important; + } + th.visible-md.visible-sm, + td.visible-md.visible-sm { + display: table-cell !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} + +@media (min-width: 1200px) { + .visible-md.visible-lg { + display: block !important; + } + tr.visible-md.visible-lg { + display: table-row !important; + } + th.visible-md.visible-lg, + td.visible-md.visible-lg { + display: table-cell !important; + } +} + +.visible-lg { + display: none !important; +} + +tr.visible-lg { + display: none !important; +} + +th.visible-lg, +td.visible-lg { + display: none !important; +} + +@media (max-width: 767px) { + .visible-lg.visible-xs { + display: block !important; + } + tr.visible-lg.visible-xs { + display: table-row !important; + } + th.visible-lg.visible-xs, + td.visible-lg.visible-xs { + display: table-cell !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-lg.visible-sm { + display: block !important; + } + tr.visible-lg.visible-sm { + display: table-row !important; + } + th.visible-lg.visible-sm, + td.visible-lg.visible-sm { + display: table-cell !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-lg.visible-md { + display: block !important; + } + tr.visible-lg.visible-md { + display: table-row !important; + } + th.visible-lg.visible-md, + td.visible-lg.visible-md { + display: table-cell !important; + } +} + +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} + +.hidden-xs { + display: block !important; +} + +tr.hidden-xs { + display: table-row !important; +} + +th.hidden-xs, +td.hidden-xs { + display: table-cell !important; +} + +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } + tr.hidden-xs { + display: none !important; + } + th.hidden-xs, + td.hidden-xs { + display: none !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .hidden-xs.hidden-sm { + display: none !important; + } + tr.hidden-xs.hidden-sm { + display: none !important; + } + th.hidden-xs.hidden-sm, + td.hidden-xs.hidden-sm { + display: none !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-xs.hidden-md { + display: none !important; + } + tr.hidden-xs.hidden-md { + display: none !important; + } + th.hidden-xs.hidden-md, + td.hidden-xs.hidden-md { + display: none !important; + } +} + +@media (min-width: 1200px) { + .hidden-xs.hidden-lg { + display: none !important; + } + tr.hidden-xs.hidden-lg { + display: none !important; + } + th.hidden-xs.hidden-lg, + td.hidden-xs.hidden-lg { + display: none !important; + } +} + +.hidden-sm { + display: block !important; +} + +tr.hidden-sm { + display: table-row !important; +} + +th.hidden-sm, +td.hidden-sm { + display: table-cell !important; +} + +@media (max-width: 767px) { + .hidden-sm.hidden-xs { + display: none !important; + } + tr.hidden-sm.hidden-xs { + display: none !important; + } + th.hidden-sm.hidden-xs, + td.hidden-sm.hidden-xs { + display: none !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } + tr.hidden-sm { + display: none !important; + } + th.hidden-sm, + td.hidden-sm { + display: none !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-sm.hidden-md { + display: none !important; + } + tr.hidden-sm.hidden-md { + display: none !important; + } + th.hidden-sm.hidden-md, + td.hidden-sm.hidden-md { + display: none !important; + } +} + +@media (min-width: 1200px) { + .hidden-sm.hidden-lg { + display: none !important; + } + tr.hidden-sm.hidden-lg { + display: none !important; + } + th.hidden-sm.hidden-lg, + td.hidden-sm.hidden-lg { + display: none !important; + } +} + +.hidden-md { + display: block !important; +} + +tr.hidden-md { + display: table-row !important; +} + +th.hidden-md, +td.hidden-md { + display: table-cell !important; +} + +@media (max-width: 767px) { + .hidden-md.hidden-xs { + display: none !important; + } + tr.hidden-md.hidden-xs { + display: none !important; + } + th.hidden-md.hidden-xs, + td.hidden-md.hidden-xs { + display: none !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .hidden-md.hidden-sm { + display: none !important; + } + tr.hidden-md.hidden-sm { + display: none !important; + } + th.hidden-md.hidden-sm, + td.hidden-md.hidden-sm { + display: none !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } + tr.hidden-md { + display: none !important; + } + th.hidden-md, + td.hidden-md { + display: none !important; + } +} + +@media (min-width: 1200px) { + .hidden-md.hidden-lg { + display: none !important; + } + tr.hidden-md.hidden-lg { + display: none !important; + } + th.hidden-md.hidden-lg, + td.hidden-md.hidden-lg { + display: none !important; + } +} + +.hidden-lg { + display: block !important; +} + +tr.hidden-lg { + display: table-row !important; +} + +th.hidden-lg, +td.hidden-lg { + display: table-cell !important; +} + +@media (max-width: 767px) { + .hidden-lg.hidden-xs { + display: none !important; + } + tr.hidden-lg.hidden-xs { + display: none !important; + } + th.hidden-lg.hidden-xs, + td.hidden-lg.hidden-xs { + display: none !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .hidden-lg.hidden-sm { + display: none !important; + } + tr.hidden-lg.hidden-sm { + display: none !important; + } + th.hidden-lg.hidden-sm, + td.hidden-lg.hidden-sm { + display: none !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-lg.hidden-md { + display: none !important; + } + tr.hidden-lg.hidden-md { + display: none !important; + } + th.hidden-lg.hidden-md, + td.hidden-lg.hidden-md { + display: none !important; + } +} + +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } + tr.hidden-lg { + display: none !important; + } + th.hidden-lg, + td.hidden-lg { + display: none !important; + } +} + +.visible-print { + display: none !important; +} + +tr.visible-print { + display: none !important; +} + +th.visible-print, +td.visible-print { + display: none !important; +} + +@media print { + .visible-print { + display: block !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } + .hidden-print { + display: none !important; + } + tr.hidden-print { + display: none !important; + } + th.hidden-print, + td.hidden-print { + display: none !important; + } +} \ No newline at end of file diff --git a/rhodecode/public/css/codemirror.css b/kallithea/public/css/codemirror.css rename from rhodecode/public/css/codemirror.css rename to kallithea/public/css/codemirror.css --- a/rhodecode/public/css/codemirror.css +++ b/kallithea/public/css/codemirror.css @@ -192,6 +192,16 @@ div.CodeMirror span.CodeMirror-nonmatchi white-space: pre-wrap; word-break: normal; } +.CodeMirror-code pre { + border-right: 30px solid transparent; + width: -webkit-fit-content; + width: -moz-fit-content; + width: fit-content; +} +.CodeMirror-wrap .CodeMirror-code pre { + border-right: none; + width: auto; +} .CodeMirror-linebackground { position: absolute; left: 0; right: 0; top: 0; bottom: 0; diff --git a/rhodecode/public/css/contextbar.css b/kallithea/public/css/contextbar.css rename from rhodecode/public/css/contextbar.css rename to kallithea/public/css/contextbar.css --- a/rhodecode/public/css/contextbar.css +++ b/kallithea/public/css/contextbar.css @@ -2,57 +2,85 @@ * Stylesheets for the context bar */ -#quick .repo_switcher { background-image: url("../images/icons/database.png"); } -#quick .journal { background-image: url("../images/icons/book.png"); } -#quick .gists { background-image: url("../images/icons/note.png"); } -#quick .gists-private { background-image: url("../images/icons/note_error.png"); } -#quick .gists-new { background-image: url("../images/icons/note_add.png"); } -#quick .search { background-image: url("../images/icons/search_16.png"); } -#quick .admin { background-image: url("../images/icons/cog_edit.png"); } +i.icon-archive { background-image: url("../images/icons/database_edit.png"); } +i.icon-arrow-right { background-image: url('../images/icons/arrow_right.png');} +i.icon-ban-circle { background-image: url("../images/icons/cancel.png"); } +i.icon-bar-chart { background-image: url("../images/icons/chart_bar.png"); } +i.icon-book { background-image: url("../images/icons/book.png"); } +i.icon-bookmark { background-image: url("../images/icons/tag_green.png"); } +i.icon-code-fork { background-image: url("../images/icons/arrow_branch.png"); } +i.icon-code-merge { background-image: url("../images/icons/arrow_merge.png"); } /* unused! */ +i.icon-cog { background-image: url("../images/icons/cog_edit.png"); } +i.icon-cog { background-image: url("../images/icons/cog.png"); } +i.icon-cogs { background-image: url("../images/icons/table_gear.png"); } +i.icon-ellipsis-horizontal:after { content: ' ...';} +i.icon-eye-open { background-image: url("../images/icons/eye.png"); } +i.icon-file-2 { background-image: url("../images/icons/note.png"); } +i.icon-file-alt { background-image: url("../images/icons/note_add.png"); } +i.icon-file { background-image: url("../images/icons/file.png"); } +i.icon-file-text { background-image: url("../images/icons/clipboard_16.png"); } +i.icon-file-txt { background-image: url("../images/icons/note_error.png"); } +i.icon-folder-close { background-image: url("../images/icons/database_link.png"); } +i.icon-git { background-image: url('../images/icons/giticon.png');} +i.icon-group { background-image: url("../images/icons/group_edit.png"); } +i.icon-heart { background-image: url("../images/icons/heart_delete.png"); } +i.icon-heart-empty { background-image: url("../images/icons/heart.png"); } +i.icon-hg { background-image: url('../images/icons/hgicon.png');} +i.icon-key { background-image: url("../images/icons/server_key.png"); } +i.icon-lock { background-image: url('../images/icons/lock.png');} +i.icon-lock-alt { background-image: url('../images/icons/private_repo.png');} +i.icon-loop { background-image: url('../images/icons/arrow_inout.png');} +i.icon-loop-2 { background-image: url('../images/icons/arrow_inout.png');} +i.icon-private { background-image: url('../images/icons/private_repo.png');} +i.icon-public { background-image: url('../images/icons/public_repo.png');} +i.icon-random { background-image: url("../images/icons/arrow_switch.png"); } +i.icon-refresh { background-image: url('../images/icons/arrow_refresh.png');} +i.icon-search { background-image: url("../images/icons/search_16.png"); } +i.icon-tag { background-image: url("../images/icons/tag_blue.png"); } +i.icon-time { background-image: url("../images/icons/time.png"); } +i.icon-list-alt { background-image: url("../images/icons/time.png"); } +i.icon-unlock { background-image: url('../images/icons/lock_open.png');} +i.icon-unlock-alt { background-image: url('../images/icons/public_repo.png');} +i.icon-user { background-image: url("../images/icons/user_edit.png"); } +i.icon-wrench { background-image: url("../images/icons/wrench.png"); } +i.icon-rss-sign { background-image: url('../images/icons/rss_16.png');} +i.icon-plus-sign { background-image: url('../images/icons/add.png');} +i.icon-chevron-left:after { content: "\00AB";} +i.icon-chevron-right:after { content: "\00BB";} +i.icon-copy { background-image: url('../images/icons/note_add.png');} +i.icon-pencil { background-image: url('../images/icons/application_form_edit.png');} +i.icon-remove { background-image: url('../images/icons/delete.png');} +i.icon-remove-sign { background-image: url('../images/icons/delete.png');} +i.icon-plus { background-image: url('../images/icons/plus_16.png');} +i.icon-resize-vertical { background-image: url('../images/icons/text_align_left.png');} +i.icon-ok-sign { background-image: url('../images/icons/tick.png');} +i.icon-minus-sign { background-image: url('../images/icons/delete.png');} +i.icon-disabled { background-image: url('../images/icons/shading.png');} /* todo: use instead of minus sign */ -#context-bar a.follow { background-image: url("../images/icons/heart.png"); } -#context-bar a.following { background-image: url("../images/icons/heart_delete.png"); } -#context-bar a.fork { background-image: url("../images/icons/arrow_divide.png"); } -#context-bar a.summary { background-image: url("../images/icons/clipboard_16.png"); } -#context-bar a.changelogs { background-image: url("../images/icons/time.png"); } -#context-bar a.files { background-image: url("../images/icons/file.png"); } -#context-bar a.switch-to { background-image: url("../images/icons/arrow_switch.png"); } -#context-bar a.options { background-image: url("../images/icons/table_gear.png"); } -#context-bar a.forks { background-image: url("../images/icons/arrow_divide.png"); } -#context-bar a.pull-request { background-image: url("../images/icons/arrow_join.png"); } -#context-bar a.branches { background-image: url("../images/icons/arrow_branch.png"); } -#context-bar a.tags { background-image: url("../images/icons/tag_blue.png"); } -#context-bar a.bookmarks { background-image: url("../images/icons/tag_green.png"); } -#context-bar a.settings { background-image: url("../images/icons/cog.png"); } -#context-bar a.search { background-image: url("../images/icons/search_16.png"); } -#context-bar a.admin { background-image: url("../images/icons/cog_edit.png"); } - -#context-bar a.journal { background-image: url("../images/icons/book.png"); } -#context-bar a.gists { background-image: url("../images/icons/note.png"); } -#context-bar a.gists-private { background-image: url("../images/icons/note_error.png"); } -#context-bar a.gists-new { background-image: url("../images/icons/note_add.png"); } -#context-bar a.repos { background-image: url("../images/icons/database_edit.png"); } -#context-bar a.repos_groups { background-image: url("../images/icons/database_link.png"); } -#context-bar a.users { background-image: url("../images/icons/user_edit.png"); } -#context-bar a.groups { background-image: url("../images/icons/group_edit.png"); } -#context-bar a.permissions { background-image: url("../images/icons/key.png"); } -#context-bar a.ldap { background-image: url("../images/icons/server_key.png"); } -#context-bar a.defaults { background-image: url("../images/icons/wrench.png"); } -#context-bar a.settings { background-image: url("../images/icons/cog_edit.png"); } -#context-bar a.compare_request { background-image: url('../images/icons/arrow_inout.png')} -#context-bar a.locking_del { background-image: url('../images/icons/lock_delete.png')} -#context-bar a.locking_add { background-image: url('../images/icons/lock_add.png')} +i[class^='icon-'] { + background-repeat: no-repeat; + background-position: center; + display: inline-block; + width: 16px; + height: 16px; + margin: -2px 0 -4px 0; + /* background-color: red; /* for debugging */ +} #content #context-bar { position: relative; overflow: visible; - background-color: #336699; + background-color: #577632; border-top: 1px solid #517da8; border-bottom: 1px solid #003162; padding: 0 5px; min-height: 36px; } +#content #context-bar h2 { + display: inline-block; +} + #header #header-inner #quick a, #content #context-bar, #content #context-bar a { @@ -133,14 +161,14 @@ ul.horizontal-list li a { #context-pages, #context-pages ul { background: #3b6998; /* Old browsers */ - background: -moz-linear-gradient(top, #4574a2 0%, #2f5d8b 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#4574a2), color-stop(100%,#2f5d8b)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #4574a2 0%, #2f5d8b 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #4574a2 0%, #2f5d8b 100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, #4574a2 0%, #2f5d8b 100%); /* IE10+ */ - background: linear-gradient(to bottom, #4574a2 0%, #2f5d8b 100%); /* W3C */ + background: -moz-linear-gradient(top, #577632 0%, #577632 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#577632), color-stop(100%,#577632)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #577632 0%, #577632 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #577632 0%, #577632 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #577632 0%, #577632 100%); /* IE10+ */ + background: linear-gradient(to bottom, #577632 0%, #577632 100%); /* W3C */ /*Filter on IE will also use overflow:hidden implicitly, and that would clip our inner menus.*/ - /*filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4574a2', endColorstr='#2f5d8b',GradientType=0 ); /* IE6-9 */*/ + /*filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#577632', endColorstr='#577632',GradientType=0 ); /* IE6-9 */*/ } #header #header-inner #quick a, @@ -160,7 +188,7 @@ ul#context-actions { display: inline-block; float: right; border-radius: 4px; - background-image: linear-gradient(top, #4574a2 0%, #2f5d8b 100%); + background-image: linear-gradient(top, #577632 0%, #577632 100%); } #content ul#context-actions li { @@ -270,8 +298,7 @@ ul#context-actions { #context-pages a, #context-pages .admin_menu a { display: block; - padding: 0px 10px 1px 30px; - padding-left: 30px; + padding: 0px 10px 1px 10px; line-height: 35px; } diff --git a/rhodecode/public/css/mergerly.css b/kallithea/public/css/mergely.css rename from rhodecode/public/css/mergerly.css rename to kallithea/public/css/mergely.css --- a/rhodecode/public/css/mergerly.css +++ b/kallithea/public/css/mergely.css @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2013 by Jamie Peabody, http://www.mergely.com + * All rights reserved. + * Version: 3.3.4 2013-11-02 + * + * NOTE by bkuhn@sfconservancy.org for Kallithea: + * Mergely license appears at http://www.mergely.com/license.php and in LICENSE-MERGELY.html + */ /* required */ .mergely-column textarea { width: 80px; height: 200px; } @@ -12,17 +20,17 @@ .mergely-column { border: 1px solid #ccc; } .mergely-active { border: 1px solid #a3d1ff; } -.mergely.a.rhs.start { border-top: 1px solid #ddffdd; } +.mergely.a.rhs.start { border-top: 1px solid #a3d1ff; } .mergely.a.lhs.start.end, -.mergely.a.rhs.end { border-bottom: 1px solid #ddffdd; } -.mergely.a.rhs { background-color: #ddffdd; } -.mergely.a.lhs.start.end.first { border-bottom: 0; border-top: 1px solid #ddffdd; } +.mergely.a.rhs.end { border-bottom: 1px solid #a3d1ff; } +.mergely.a.rhs { background-color: #ddeeff; } +.mergely.a.lhs.start.end.first { border-bottom: 0; border-top: 1px solid #a3d1ff; } .mergely.d.lhs { background-color: #edc0c0; } .mergely.d.lhs.end, -.mergely.d.rhs.start.end { border-bottom: 1px solid #ffdddd; } -.mergely.d.rhs.start.end.first { border-bottom: 0; border-top: 1px solid #ffdddd; } -.mergely.d.lhs.start { border-top: 1px solid #ffdddd; } +.mergely.d.rhs.start.end { border-bottom: 1px solid #ff7f7f; } +.mergely.d.rhs.start.end.first { border-bottom: 0; border-top: 1px solid #ff7f7f; } +.mergely.d.lhs.start { border-top: 1px solid #ff7f7f; } .mergely.c.lhs, .mergely.c.rhs { background-color: #fafafa; } @@ -31,11 +39,5 @@ .mergely.c.lhs.end, .mergely.c.rhs.end { border-bottom: 1px solid #a3a3a3; } -.mergely.ch.a.rhs { background-color: #ddffdd; } -.mergely.ch.d.lhs { background-color: #ffdddd; } - - -.mergely-margin #compare-lhs-margin, -.mergely-margin #compare-rhs-margin { - cursor: pointer -} +.mergely.ch.a.rhs { background-color: #ddeeff; } +.mergely.ch.d.lhs { background-color: #edc0c0; text-decoration: line-through; color: #888; } diff --git a/rhodecode/public/css/pygments.css b/kallithea/public/css/pygments.css rename from rhodecode/public/css/pygments.css rename to kallithea/public/css/pygments.css diff --git a/rhodecode/public/css/style.css b/kallithea/public/css/style.css old mode 100755 new mode 100644 rename from rhodecode/public/css/style.css rename to kallithea/public/css/style.css --- a/rhodecode/public/css/style.css +++ b/kallithea/public/css/style.css @@ -50,13 +50,13 @@ html { } a { - color: #003367; + color: #577632; text-decoration: none; cursor: pointer; } a:hover { - color: #316293; + color: #576622; text-decoration: underline; } @@ -249,24 +249,40 @@ div:hover > a.permalink { visibility: visible; } -#header { -} +#header #logo { + padding-left: 20px; +} + +div.header img { + padding-top: 5px; +} + +#header #logo div.header, +#header #logo div.branding { + font-size: 20px; + color: white; + float: left; + height: 44px; + line-height: 44px; + margin-right: 5px; +} + #header ul#logged-user { margin-bottom: 5px !important; -webkit-border-radius: 0px 0px 8px 8px; -khtml-border-radius: 0px 0px 8px 8px; border-radius: 0px 0px 8px 8px; height: 37px; - background-color: #003B76; + background-color: #577632; background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); - background-image: -moz-linear-gradient(top, #003b76, #00376e); - background-image: -ms-linear-gradient(top, #003b76, #00376e); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) ); - background-image: -webkit-linear-gradient(top, #003b76, #00376e); - background-image: -o-linear-gradient(top, #003b76, #00376e); - background-image: linear-gradient(to bottom, #003b76, #00376e); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 ); + background-image: -khtml-gradient(linear, left top, left bottom, from(#577632), to(#577632) ); + background-image: -moz-linear-gradient(top, #577632, #577632); + background-image: -ms-linear-gradient(top, #577632, #577632); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #577632), color-stop(100%, #577632) ); + background-image: -webkit-linear-gradient(top, #577632, #577632); + background-image: -o-linear-gradient(top, #577632, #577632); + background-image: linear-gradient(to bottom, #577632, #577632); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#577632',endColorstr='#577632', GradientType=0 ); box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); } @@ -275,7 +291,7 @@ div:hover > a.permalink { float: left; margin: 8px 0 0; padding: 4px 12px; - border-left: 1px solid #316293; + border-left: 1px solid #576622; } #header ul#logged-user li.first { @@ -316,7 +332,7 @@ div:hover > a.permalink { #header-dd { clear: both; position: fixed !important; - background-color: #003B76; + background-color: #577632; opacity: 0.01; cursor: pointer; min-height: 10px; @@ -337,16 +353,16 @@ div:hover > a.permalink { min-height: 44px; clear: both; position: relative; - background-color: #003B76; + background-color: #577632; background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); - background-image: -moz-linear-gradient(top, #003b76, #00376e); - background-image: -ms-linear-gradient(top, #003b76, #00376e); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76),color-stop(100%, #00376e) ); - background-image: -webkit-linear-gradient(top, #003b76, #00376e); - background-image: -o-linear-gradient(top, #003b76, #00376e); - background-image: linear-gradient(to bottom, #003b76, #00376e); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 ); + background-image: -khtml-gradient(linear, left top, left bottom, from(#577632), to(#577632) ); + background-image: -moz-linear-gradient(top, #577632, #577632); + background-image: -ms-linear-gradient(top, #577632, #577632); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #577632),color-stop(100%, #577632) ); + background-image: -webkit-linear-gradient(top, #577632, #577632); + background-image: -o-linear-gradient(top, #577632, #577632); + background-image: linear-gradient(to bottom, #577632, #577632); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#577632',endColorstr='#577632', GradientType=0 ); margin: 0; padding: 0; display: block; @@ -606,7 +622,7 @@ td.quick_repo_menu { td.quick_repo_menu.active { background: url("../images/dt-arrow-dn.png") no-repeat scroll 5px 50% #FFFFFF !important; - border: 1px solid #003367; + border: 1px solid #577632; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); cursor: pointer; } @@ -618,7 +634,7 @@ td.quick_repo_menu .menu_items { position: absolute; background-color: #FFF; background: none repeat scroll 0 0 #FFFFFF; - border-color: #003367 #666666 #666666; + border-color: #577632 #666666 #666666; border-right: 1px solid #666666; border-style: solid; border-width: 1px; @@ -944,16 +960,16 @@ tbody .yui-dt-editable { cursor: pointer #content div.box div.title { clear: both; overflow: hidden; - background-color: #003B76; + background-color: #577632; background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); - background-image: -moz-linear-gradient(top, #003b76, #00376e); - background-image: -ms-linear-gradient(top, #003b76, #00376e); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) ); - background-image: -webkit-linear-gradient(top, #003b76, #00376e); - background-image: -o-linear-gradient(top, #003b76, #00376e); - background-image: linear-gradient(to bottom, #003b76, #00376e); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 ); + background-image: -khtml-gradient(linear, left top, left bottom, from(#577632), to(#577632) ); + background-image: -moz-linear-gradient(top, #577632, #577632); + background-image: -ms-linear-gradient(top, #577632, #577632); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #577632), color-stop(100%, #577632) ); + background-image: -webkit-linear-gradient(top, #577632, #577632); + background-image: -o-linear-gradient(top, #577632, #577632); + background-image: linear-gradient(to bottom, #577632, #577632); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#577632', endColorstr='#577632', GradientType=0 ); margin: 0 0 20px; padding: 0; border-radius: 4px 4px 0 0; @@ -983,15 +999,10 @@ tbody .yui-dt-editable { cursor: pointer } #content div.box div.title ul.links li a { - border-left: 1px solid #316293; - color: #FFFFFF; - display: block; - float: left; font-size: 13px; font-weight: 700; height: 1%; - margin: 0; - padding: 11px 22px 12px; + margin: 4px; text-decoration: none; } @@ -999,9 +1010,7 @@ tbody .yui-dt-editable { cursor: pointer #content div.box div.h1, #content div.box div.h2, #content div.box div.h3, #content div.box div.h4, #content div.box div.h5, #content div.box div.h6 { clear: both; overflow: hidden; - border-bottom: 1px solid #DDD; - margin: 10px 20px; - padding: 0 0 15px; + margin: 8px 20px 5px; } #content div.box p { @@ -1298,6 +1307,9 @@ tbody .yui-dt-editable { cursor: pointer #content div.box div.form div.fields div.field div.file { margin: 0 0 0 200px; } +#content div.box div.form div.fields div.field div.editor { + margin: 0 0 0 200px; +} #content div.box-left div.form div.fields div.field div.input, #content div.box-right div.form div.fields div.field div.input { margin: 0 0 0 0px; @@ -1692,6 +1704,7 @@ div.form div.fields div.field div.button #content div.box #summary { margin-right: 200px; + min-height: 240px; } #summary-menu-stats { @@ -1731,7 +1744,7 @@ div.form div.fields div.field div.button #summary-menu-stats a { display: block; - padding: 12px 30px; + padding: 12px 10px; background-repeat: no-repeat; background-position: 10px 50%; padding-right: 10px; @@ -1825,7 +1838,7 @@ div.form div.fields div.field div.button } a.metatag[tag="license"]:hover { - background-color: #003367; + background-color: #577632; color: #FFF; text-decoration: none; } @@ -1852,16 +1865,16 @@ a.metatag[tag="license"]:hover { } #footer div#footer-inner { - background-color: #003B76; + background-color: #577632; background-repeat: repeat-x; - background-image: -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E)); - background-image: -moz-linear-gradient(top, #003b76, #00376e); - background-image: -ms-linear-gradient( top, #003b76, #00376e); - background-image: -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e)); - background-image: -webkit-linear-gradient( top, #003b76, #00376e)); - background-image: -o-linear-gradient( top, #003b76, #00376e)); - background-image: linear-gradient(to bottom, #003b76, #00376e); - filter: progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0); + background-image: -khtml-gradient( linear, left top, left bottom, from(#577632), to(#577632)); + background-image: -moz-linear-gradient(top, #577632, #577632); + background-image: -ms-linear-gradient( top, #577632, #577632); + background-image: -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #577632), color-stop( 100%, #577632)); + background-image: -webkit-linear-gradient( top, #577632, #577632)); + background-image: -o-linear-gradient( top, #577632, #577632)); + background-image: linear-gradient(to bottom, #577632, #577632); + filter: progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#577632', endColorstr = '#577632', GradientType = 0); box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); -webkit-border-radius: 4px 4px 4px 4px; -khtml-border-radius: 4px 4px 4px 4px; @@ -1887,16 +1900,16 @@ a.metatag[tag="license"]:hover { clear: both; overflow: hidden; position: relative; - background-color: #003B76; + background-color: #577632; background-repeat: repeat-x; - background-image: -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E)); - background-image: -moz-linear-gradient( top, #003b76, #00376e); - background-image: -ms-linear-gradient( top, #003b76, #00376e); - background-image: -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e)); - background-image: -webkit-linear-gradient( top, #003b76, #00376e)); - background-image: -o-linear-gradient( top, #003b76, #00376e)); - background-image: linear-gradient(to bottom, #003b76, #00376e); - filter: progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0); + background-image: -khtml-gradient( linear, left top, left bottom, from(#577632), to(#577632)); + background-image: -moz-linear-gradient( top, #577632, #577632); + background-image: -ms-linear-gradient( top, #577632, #577632); + background-image: -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #577632), color-stop( 100%, #577632)); + background-image: -webkit-linear-gradient( top, #577632, #577632)); + background-image: -o-linear-gradient( top, #577632, #577632)); + background-image: linear-gradient(to bottom, #577632, #577632); + filter: progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#577632', endColorstr = '#577632', GradientType = 0); margin: 0 auto; padding: 0; } @@ -1970,16 +1983,16 @@ a.metatag[tag="license"]:hover { padding: 4px; position: absolute; right: 0; - background-color: #003B76; + background-color: #577632; background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); - background-image: -moz-linear-gradient(top, #003b76, #00376e); - background-image: -ms-linear-gradient(top, #003b76, #00376e); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) ); - background-image: -webkit-linear-gradient(top, #003b76, #00376e); - background-image: -o-linear-gradient(top, #003b76, #00376e); - background-image: linear-gradient(to bottom, #003b76, #00376e); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 ); + background-image: -khtml-gradient(linear, left top, left bottom, from(#577632), to(#577632) ); + background-image: -moz-linear-gradient(top, #577632, #577632); + background-image: -ms-linear-gradient(top, #577632, #577632); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #577632), color-stop(100%, #577632) ); + background-image: -webkit-linear-gradient(top, #577632, #577632); + background-image: -o-linear-gradient(top, #577632, #577632); + background-image: linear-gradient(to bottom, #577632, #577632); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#577632', endColorstr='#577632', GradientType=0 ); z-index: 999; -webkit-border-radius: 0px 0px 4px 4px; @@ -2137,17 +2150,17 @@ a.metatag[tag="license"]:hover { clear: both; overflow: hidden; position: relative; - background-color: #003B76; + background-color: #577632; background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); - background-image: -moz-linear-gradient(top, #003b76, #00376e); - background-image: -ms-linear-gradient(top, #003b76, #00376e); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) ); - background-image: -webkit-linear-gradient(top, #003b76, #00376e); - background-image: -o-linear-gradient(top, #003b76, #00376e); - background-image: linear-gradient(to bottom, #003b76, #00376e); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', - endColorstr='#00376e', GradientType=0 ); + background-image: -khtml-gradient(linear, left top, left bottom, from(#577632), to(#577632) ); + background-image: -moz-linear-gradient(top, #577632, #577632); + background-image: -ms-linear-gradient(top, #577632, #577632); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #577632), color-stop(100%, #577632) ); + background-image: -webkit-linear-gradient(top, #577632, #577632); + background-image: -o-linear-gradient(top, #577632, #577632); + background-image: linear-gradient(to bottom, #577632, #577632); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#577632', + endColorstr='#577632', GradientType=0 ); margin: 0 auto; padding: 0; } @@ -2287,7 +2300,7 @@ a.metatag[tag="license"]:hover { } .trending_language { - background-color: #003367; + background-color: #577632; color: #FFF; display: block; min-width: 20px; @@ -2403,7 +2416,7 @@ h3.files_location { .cs_files .changes { float: right; - color: #003367; + color: #577632; } .cs_files .changes .added { @@ -2572,6 +2585,12 @@ BIN_FILENODE = 6 font-size: 10px; } +#graph_content_pr .compare_view_commits .expand_commit, +#graph_content .container .expand_commit { + width: 24px; + cursor: pointer; +} + #graph_content #changesets .container .right { width: 120px; padding-right: 0px; @@ -2797,7 +2816,7 @@ BIN_FILENODE = 6 .spantag { padding: 1px 3px 1px 3px; font-size: 10px; - color: #336699; + color: #577632; white-space: nowrap; -webkit-border-radius: 4px; border-radius: 4px; @@ -2977,10 +2996,7 @@ table.code-browser .browser-file { height: 16px; } .diffblock .changeset_file { - background: url("../images/icons/file.png") no-repeat scroll 3px; - text-align: left; float: left; - padding: 2px 0px 2px 22px; } .diffblock .diff-menu-wrapper { float: left; @@ -2989,7 +3005,7 @@ table.code-browser .browser-file { .diffblock .diff-menu { position: absolute; background: none repeat scroll 0 0 #FFFFFF; - border-color: #003367 #666666 #666666; + border-color: #577632 #666666 #666666; border-right: 1px solid #666666; border-style: solid solid solid; border-width: 1px; @@ -3049,7 +3065,7 @@ table.code-browser .submodule-dir { } .box .search div.search_path div.link a { - color: #003367; + color: #577632; cursor: pointer; text-decoration: none; } @@ -3066,7 +3082,7 @@ table.code-browser .submodule-dir { } .info_box .rev { - color: #003367; + color: #577632; font-size: 1.6em; font-weight: bold; vertical-align: sub; @@ -3089,6 +3105,11 @@ table.code-browser .submodule-dir { padding: 4px 3px 2px 2px; } +.info_box_elem { + display: inline-block; + padding: 0 2px; +} + .yui-overlay, .yui-panel-container { visibility: hidden; position: absolute; @@ -3099,7 +3120,7 @@ table.code-browser .submodule-dir { position: absolute; background-color: #FFF; - border: 2px solid #003367; + border: 2px solid #577632; font: 100% sans-serif; width: auto; opacity: 1; @@ -3115,11 +3136,11 @@ table.code-browser .submodule-dir { } .hl-tip-box { - visibility: hidden; + z-index: 1; position: absolute; color: #666; background-color: #FFF; - border: 2px solid #003367; + border: 2px solid #577632; font: 100% sans-serif; width: auto; opacity: 1; @@ -3389,7 +3410,7 @@ table.code-browser .submodule-dir { color: red; } -.error_msg { +.flash_msg .alert-error { background-color: #c43c35; background-repeat: repeat-x; background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35) ); @@ -3403,11 +3424,11 @@ table.code-browser .submodule-dir { border-color: #c43c35 #c43c35 #882a25; } -.error_msg a { +.flash_msg .alert-error a { text-decoration: underline; } -.warning_msg { +.flash_msg .alert-warning { color: #404040 !important; background-color: #eedc94; background-repeat: repeat-x; @@ -3422,11 +3443,11 @@ table.code-browser .submodule-dir { border-color: #eedc94 #eedc94 #e4c652; } -.warning_msg a { +.flash_msg .alert-warning a { text-decoration: underline; } -.success_msg { +.flash_msg .alert-success { background-color: #57a957; background-repeat: repeat-x !important; background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957) ); @@ -3440,12 +3461,12 @@ table.code-browser .submodule-dir { border-color: #57a957 #57a957 #3d773d; } -.success_msg a { +.flash_msg .alert-success a { text-decoration: underline; color: #FFF !important; } -.notice_msg { +.flash_msg .alert-info { background-color: #339bb9; background-repeat: repeat-x; background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9) ); @@ -3459,11 +3480,14 @@ table.code-browser .submodule-dir { border-color: #339bb9 #339bb9 #22697d; } -.notice_msg a { +.flash_msg .alert-info a { text-decoration: underline; } -.success_msg, .error_msg, .notice_msg, .warning_msg { +.flash_msg .alert-error, +.flash_msg .alert-warning, +.flash_msg .alert-success, +.flash_msg .alert-info { font-size: 12px; font-weight: 700; min-height: 14px; @@ -3551,14 +3575,14 @@ div.gravatar img { } #content div.box div.title div.search { - border-left: 1px solid #316293; + border-left: 1px solid #576622; } #content div.box div.title div.search div.input input { - border: 1px solid #316293; -} - -.ui-btn { + border: 1px solid #576622; +} + +.btn { color: #515151; background-color: #DADADA; background-repeat: repeat-x; @@ -3584,26 +3608,55 @@ div.gravatar img { cursor: pointer !important; padding: 3px 3px 3px 3px; background-position: 0 -100px; - -} - -.ui-btn.badge { + display: inline-block; +} + +ul.nav-stacked { + margin: 20px; + color: #393939; + font-weight: 700; +} + +ul.nav-stacked a { + color: inherit; +} + +/* make .btn inputs and buttons and divs look the same */ +button.btn, +input.btn { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +.btn::-moz-focus-inner { + border: 0; + padding: 0; +} + +.btn.badge { cursor: default !important; } -.ui-btn.disabled { +.btn.disabled { color: #999; } -.ui-btn.xsmall { - padding: 1px 2px 1px 1px; -} - -.ui-btn.large { - padding: 6px 12px; -} - -.ui-btn.clone { +.btn.btn-danger.disabled { + color: #eee; + background-color: #c77; + border-color: #b66 +} + +.btn.btn-small { + padding: 2px 6px; +} + +.btn.btn-mini { + padding: 0px 4px; +} + +.btn.clone { padding: 5px 2px 6px 1px; margin: 0px 0px 3px -4px; -webkit-border-radius: 0px 4px 4px 0px !important; @@ -3615,26 +3668,26 @@ div.gravatar img { position: relative; top: -2px; } -.ui-btn:focus { +.btn:focus { outline: none; } -.ui-btn:hover { +.btn:hover { background-position: 0 -100px; text-decoration: none; color: #515151; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 0 3px #FFFFFF !important; } -.ui-btn.badge:hover { +.btn.badge:hover { box-shadow: none !important; } -.ui-btn.disabled:hover { +.btn.disabled:hover { background-position: 0; color: #999; text-decoration: none; box-shadow: none !important; } -.ui-btn.red { +.btn.red { color: #fff; background-color: #c43c35; background-repeat: repeat-x; @@ -3651,7 +3704,7 @@ div.gravatar img { } -.ui-btn.blue { +.btn.blue { color: #fff; background-color: #339bb9; background-repeat: repeat-x; @@ -3667,7 +3720,7 @@ div.gravatar img { border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); } -.ui-btn.green { +.btn.green { color: #fff; background-color: #57a957; background-repeat: repeat-x; @@ -3683,7 +3736,7 @@ div.gravatar img { border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); } -.ui-btn.yellow { +.btn.yellow { color: #fff; background-color: #faa732; background-repeat: repeat-x; @@ -3703,11 +3756,11 @@ label.disabled { color: #aaa; } -.ui-btn.blue.hidden { +.btn.blue.hidden { display: none; } -.ui-btn.active { +.btn.active { font-weight: bold; } @@ -3756,6 +3809,42 @@ div#legend_data, div#legend_container, d display: block; } +.repo-switcher .select2-choice { + padding: 0px 8px 1px !important; + display: block; + height: 100%; +} + +.repo-switcher .select2-container, +.repo-switcher .select2-choice, +.repo-switcher .select2-choice span { + background: transparent !important; + border: 0 !important; + box-shadow: none !important; + color: #FFFFFF !important; +} + +.repo-switcher .select2-arrow { + display: none !important; +} + +.repo-switcher .select2-chosen:after { + content: ' \25BE'; +} + +.repo-switcher-dropdown.select2-drop.select2-drop-active { + xborder-color: black; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + color: #fff; + background-color: #576622; +} + +.repo-switcher-dropdown.select2-drop.select2-drop-active .select2-results .select2-highlighted { + background-color: #6388ad; +} + #content div.graph { padding: 0 10px 10px; } @@ -4073,6 +4162,10 @@ div#legend_container table td, div#legen padding: 0px 0px 0px 0px; } +.reviewer_status { + float: left; +} + .reviewers_member { height: 15px; padding: 0px 0px 0px 10px; @@ -4693,7 +4786,7 @@ span.pr-closed-tag { font-size: 10px; padding: 1px 3px 1px 3px; font-size: 10px; - color: #336699; + color: #577632; white-space: nowrap; -webkit-border-radius: 4px; border-radius: 4px; @@ -4792,7 +4885,7 @@ div.diffblock .code-header { border-bottom: 1px solid #CCCCCC; background: #EEEEEE; padding: 10px 0 10px 0; - height: 14px; + min-height: 14px; } div.diffblock .code-header.banner { @@ -4963,3 +5056,11 @@ div.comment:target>.comment-wrapp { border: solid 2px #ee0 !important; margin: -2px; } + +#help_kb { + display: none; +} + +.repo-switcher-dropdown .select2-result-label span.repo-icons { + margin-left: -12px; +} diff --git a/rhodecode/public/images/arrow_right_64.png b/kallithea/public/images/arrow_right_64.png rename from rhodecode/public/images/arrow_right_64.png rename to kallithea/public/images/arrow_right_64.png diff --git a/rhodecode/public/images/background.png b/kallithea/public/images/background.png rename from rhodecode/public/images/background.png rename to kallithea/public/images/background.png diff --git a/rhodecode/public/images/button.png b/kallithea/public/images/button.png rename from rhodecode/public/images/button.png rename to kallithea/public/images/button.png diff --git a/rhodecode/public/images/button_highlight.png b/kallithea/public/images/button_highlight.png rename from rhodecode/public/images/button_highlight.png rename to kallithea/public/images/button_highlight.png diff --git a/rhodecode/public/images/button_selected.png b/kallithea/public/images/button_selected.png rename from rhodecode/public/images/button_selected.png rename to kallithea/public/images/button_selected.png diff --git a/rhodecode/public/images/dt-arrow-dn.png b/kallithea/public/images/dt-arrow-dn.png rename from rhodecode/public/images/dt-arrow-dn.png rename to kallithea/public/images/dt-arrow-dn.png diff --git a/rhodecode/public/images/dt-arrow-up.png b/kallithea/public/images/dt-arrow-up.png rename from rhodecode/public/images/dt-arrow-up.png rename to kallithea/public/images/dt-arrow-up.png diff --git a/rhodecode/public/images/favicon.ico b/kallithea/public/images/favicon.ico rename from rhodecode/public/images/favicon.ico rename to kallithea/public/images/favicon.ico index 7c0ab2b4c643f33162c0ebd80c4b0f8418acef2c..63b1766c4244fd0bc4313177f02724123787dc61 GIT binary patch literal 6518 zc%1E6Nla5g7#qxWtRbg^On|9=w^T(Tj;1^<-kACxQac|C`s6N?%JUn+g4sk15mn=bQOw{$-)<2!Q$aPf zX^g2HY&KP)-HGcvLxHeopb6iP6aLu2Wwq02lk|0dv1+*8#2i=$T04|S>P^K+=2y?0 z*zOMbkGOh*2WWkV+y*~I?a4TZ*Y66|9d!!+vb?WB&XuUIMEG7+=bdDS4wvxP*jtHs zMBt(4Tw{{H)6j;hhC58}P%CWk4JP+ReFYLeUqSKN>UC1z;A3|BEkc{+^=JGiTyIJn*#K+w3^ZEn7yO=`K71sV4-qD5edDmd)8N-r>1X7> zM({=|JFO-`oOBQlvV=If#dc^O{%q^5*q|8v3+|dK_*A-hnJsY6xG#uhlG*Z~9KRiZ zc=`D$4tP(F@K$$y@z!CTRUqu67Mf>v_-~Y_;PlzbipHIMtlw7l>Acm zaK6?hw5y7)-KTT7jXaPID39Nz^SeoSVV$Kml?nf1iyGoV*a7D;hy7R73I>d7tY7U%*Iyb*O|DCPA^~i%{uMd<1-_h9j)V?J$9thgzJ27|44}_=PvE_@RQ&NV ziU@GZWj|3J1b*;%Z6hZgWNjv{!RnTi+oz#RK0n3d+nw~pl{YbQu15B zX*8jIFz3GKFL`tEqjr*SU#bb*I=@1-)u>bFBbmT0_z2B6nh5lvmQW&mhh&bj{B-=W z95{_S0QY7gh}Wm6Z=Kz|GL!S4Sp(StzO!H$c*h4#XOCaan16BKAJg!`GF@{oH-GH+ ThZW;r>HVkS&q+>lvP$JI_QXPx diff --git a/rhodecode/public/images/icons/accept.png b/kallithea/public/images/icons/accept.png rename from rhodecode/public/images/icons/accept.png rename to kallithea/public/images/icons/accept.png diff --git a/rhodecode/public/images/icons/add.png b/kallithea/public/images/icons/add.png rename from rhodecode/public/images/icons/add.png rename to kallithea/public/images/icons/add.png diff --git a/rhodecode/public/images/icons/address_16.png b/kallithea/public/images/icons/address_16.png rename from rhodecode/public/images/icons/address_16.png rename to kallithea/public/images/icons/address_16.png diff --git a/rhodecode/public/images/icons/anchor.png b/kallithea/public/images/icons/anchor.png rename from rhodecode/public/images/icons/anchor.png rename to kallithea/public/images/icons/anchor.png diff --git a/rhodecode/public/images/icons/application.png b/kallithea/public/images/icons/application.png rename from rhodecode/public/images/icons/application.png rename to kallithea/public/images/icons/application.png diff --git a/rhodecode/public/images/icons/application_add.png b/kallithea/public/images/icons/application_add.png rename from rhodecode/public/images/icons/application_add.png rename to kallithea/public/images/icons/application_add.png diff --git a/rhodecode/public/images/icons/application_cascade.png b/kallithea/public/images/icons/application_cascade.png rename from rhodecode/public/images/icons/application_cascade.png rename to kallithea/public/images/icons/application_cascade.png diff --git a/rhodecode/public/images/icons/application_delete.png b/kallithea/public/images/icons/application_delete.png rename from rhodecode/public/images/icons/application_delete.png rename to kallithea/public/images/icons/application_delete.png diff --git a/rhodecode/public/images/icons/application_double.png b/kallithea/public/images/icons/application_double.png rename from rhodecode/public/images/icons/application_double.png rename to kallithea/public/images/icons/application_double.png diff --git a/rhodecode/public/images/icons/application_edit.png b/kallithea/public/images/icons/application_edit.png rename from rhodecode/public/images/icons/application_edit.png rename to kallithea/public/images/icons/application_edit.png diff --git a/rhodecode/public/images/icons/application_error.png b/kallithea/public/images/icons/application_error.png rename from rhodecode/public/images/icons/application_error.png rename to kallithea/public/images/icons/application_error.png diff --git a/rhodecode/public/images/icons/application_form.png b/kallithea/public/images/icons/application_form.png rename from rhodecode/public/images/icons/application_form.png rename to kallithea/public/images/icons/application_form.png diff --git a/rhodecode/public/images/icons/application_form_add.png b/kallithea/public/images/icons/application_form_add.png rename from rhodecode/public/images/icons/application_form_add.png rename to kallithea/public/images/icons/application_form_add.png diff --git a/rhodecode/public/images/icons/application_form_delete.png b/kallithea/public/images/icons/application_form_delete.png rename from rhodecode/public/images/icons/application_form_delete.png rename to kallithea/public/images/icons/application_form_delete.png diff --git a/rhodecode/public/images/icons/application_form_edit.png b/kallithea/public/images/icons/application_form_edit.png rename from rhodecode/public/images/icons/application_form_edit.png rename to kallithea/public/images/icons/application_form_edit.png diff --git a/rhodecode/public/images/icons/application_form_magnify.png b/kallithea/public/images/icons/application_form_magnify.png rename from rhodecode/public/images/icons/application_form_magnify.png rename to kallithea/public/images/icons/application_form_magnify.png diff --git a/rhodecode/public/images/icons/application_get.png b/kallithea/public/images/icons/application_get.png rename from rhodecode/public/images/icons/application_get.png rename to kallithea/public/images/icons/application_get.png diff --git a/rhodecode/public/images/icons/application_go.png b/kallithea/public/images/icons/application_go.png rename from rhodecode/public/images/icons/application_go.png rename to kallithea/public/images/icons/application_go.png diff --git a/rhodecode/public/images/icons/application_home.png b/kallithea/public/images/icons/application_home.png rename from rhodecode/public/images/icons/application_home.png rename to kallithea/public/images/icons/application_home.png diff --git a/rhodecode/public/images/icons/application_key.png b/kallithea/public/images/icons/application_key.png rename from rhodecode/public/images/icons/application_key.png rename to kallithea/public/images/icons/application_key.png diff --git a/rhodecode/public/images/icons/application_lightning.png b/kallithea/public/images/icons/application_lightning.png rename from rhodecode/public/images/icons/application_lightning.png rename to kallithea/public/images/icons/application_lightning.png diff --git a/rhodecode/public/images/icons/application_link.png b/kallithea/public/images/icons/application_link.png rename from rhodecode/public/images/icons/application_link.png rename to kallithea/public/images/icons/application_link.png diff --git a/rhodecode/public/images/icons/application_osx.png b/kallithea/public/images/icons/application_osx.png rename from rhodecode/public/images/icons/application_osx.png rename to kallithea/public/images/icons/application_osx.png diff --git a/rhodecode/public/images/icons/application_osx_terminal.png b/kallithea/public/images/icons/application_osx_terminal.png rename from rhodecode/public/images/icons/application_osx_terminal.png rename to kallithea/public/images/icons/application_osx_terminal.png diff --git a/rhodecode/public/images/icons/application_put.png b/kallithea/public/images/icons/application_put.png rename from rhodecode/public/images/icons/application_put.png rename to kallithea/public/images/icons/application_put.png diff --git a/rhodecode/public/images/icons/application_side_boxes.png b/kallithea/public/images/icons/application_side_boxes.png rename from rhodecode/public/images/icons/application_side_boxes.png rename to kallithea/public/images/icons/application_side_boxes.png diff --git a/rhodecode/public/images/icons/application_side_contract.png b/kallithea/public/images/icons/application_side_contract.png rename from rhodecode/public/images/icons/application_side_contract.png rename to kallithea/public/images/icons/application_side_contract.png diff --git a/rhodecode/public/images/icons/application_side_expand.png b/kallithea/public/images/icons/application_side_expand.png rename from rhodecode/public/images/icons/application_side_expand.png rename to kallithea/public/images/icons/application_side_expand.png diff --git a/rhodecode/public/images/icons/application_side_list.png b/kallithea/public/images/icons/application_side_list.png rename from rhodecode/public/images/icons/application_side_list.png rename to kallithea/public/images/icons/application_side_list.png diff --git a/rhodecode/public/images/icons/application_side_tree.png b/kallithea/public/images/icons/application_side_tree.png rename from rhodecode/public/images/icons/application_side_tree.png rename to kallithea/public/images/icons/application_side_tree.png diff --git a/rhodecode/public/images/icons/application_split.png b/kallithea/public/images/icons/application_split.png rename from rhodecode/public/images/icons/application_split.png rename to kallithea/public/images/icons/application_split.png diff --git a/rhodecode/public/images/icons/application_tile_horizontal.png b/kallithea/public/images/icons/application_tile_horizontal.png rename from rhodecode/public/images/icons/application_tile_horizontal.png rename to kallithea/public/images/icons/application_tile_horizontal.png diff --git a/rhodecode/public/images/icons/application_tile_vertical.png b/kallithea/public/images/icons/application_tile_vertical.png rename from rhodecode/public/images/icons/application_tile_vertical.png rename to kallithea/public/images/icons/application_tile_vertical.png diff --git a/rhodecode/public/images/icons/application_view_columns.png b/kallithea/public/images/icons/application_view_columns.png rename from rhodecode/public/images/icons/application_view_columns.png rename to kallithea/public/images/icons/application_view_columns.png diff --git a/rhodecode/public/images/icons/application_view_detail.png b/kallithea/public/images/icons/application_view_detail.png rename from rhodecode/public/images/icons/application_view_detail.png rename to kallithea/public/images/icons/application_view_detail.png diff --git a/rhodecode/public/images/icons/application_view_gallery.png b/kallithea/public/images/icons/application_view_gallery.png rename from rhodecode/public/images/icons/application_view_gallery.png rename to kallithea/public/images/icons/application_view_gallery.png diff --git a/rhodecode/public/images/icons/application_view_icons.png b/kallithea/public/images/icons/application_view_icons.png rename from rhodecode/public/images/icons/application_view_icons.png rename to kallithea/public/images/icons/application_view_icons.png diff --git a/rhodecode/public/images/icons/application_view_list.png b/kallithea/public/images/icons/application_view_list.png rename from rhodecode/public/images/icons/application_view_list.png rename to kallithea/public/images/icons/application_view_list.png diff --git a/rhodecode/public/images/icons/application_view_tile.png b/kallithea/public/images/icons/application_view_tile.png rename from rhodecode/public/images/icons/application_view_tile.png rename to kallithea/public/images/icons/application_view_tile.png diff --git a/rhodecode/public/images/icons/application_xp.png b/kallithea/public/images/icons/application_xp.png rename from rhodecode/public/images/icons/application_xp.png rename to kallithea/public/images/icons/application_xp.png diff --git a/rhodecode/public/images/icons/application_xp_terminal.png b/kallithea/public/images/icons/application_xp_terminal.png rename from rhodecode/public/images/icons/application_xp_terminal.png rename to kallithea/public/images/icons/application_xp_terminal.png diff --git a/rhodecode/public/images/icons/arrow_branch.png b/kallithea/public/images/icons/arrow_branch.png rename from rhodecode/public/images/icons/arrow_branch.png rename to kallithea/public/images/icons/arrow_branch.png diff --git a/rhodecode/public/images/icons/arrow_divide.png b/kallithea/public/images/icons/arrow_divide.png rename from rhodecode/public/images/icons/arrow_divide.png rename to kallithea/public/images/icons/arrow_divide.png diff --git a/rhodecode/public/images/icons/arrow_down.png b/kallithea/public/images/icons/arrow_down.png rename from rhodecode/public/images/icons/arrow_down.png rename to kallithea/public/images/icons/arrow_down.png diff --git a/rhodecode/public/images/icons/arrow_in.png b/kallithea/public/images/icons/arrow_in.png rename from rhodecode/public/images/icons/arrow_in.png rename to kallithea/public/images/icons/arrow_in.png diff --git a/rhodecode/public/images/icons/arrow_inout.png b/kallithea/public/images/icons/arrow_inout.png rename from rhodecode/public/images/icons/arrow_inout.png rename to kallithea/public/images/icons/arrow_inout.png diff --git a/rhodecode/public/images/icons/arrow_join.png b/kallithea/public/images/icons/arrow_join.png rename from rhodecode/public/images/icons/arrow_join.png rename to kallithea/public/images/icons/arrow_join.png diff --git a/rhodecode/public/images/icons/arrow_left.png b/kallithea/public/images/icons/arrow_left.png rename from rhodecode/public/images/icons/arrow_left.png rename to kallithea/public/images/icons/arrow_left.png diff --git a/rhodecode/public/images/icons/arrow_merge.png b/kallithea/public/images/icons/arrow_merge.png rename from rhodecode/public/images/icons/arrow_merge.png rename to kallithea/public/images/icons/arrow_merge.png diff --git a/rhodecode/public/images/icons/arrow_out.png b/kallithea/public/images/icons/arrow_out.png rename from rhodecode/public/images/icons/arrow_out.png rename to kallithea/public/images/icons/arrow_out.png diff --git a/rhodecode/public/images/icons/arrow_redo.png b/kallithea/public/images/icons/arrow_redo.png rename from rhodecode/public/images/icons/arrow_redo.png rename to kallithea/public/images/icons/arrow_redo.png diff --git a/rhodecode/public/images/icons/arrow_refresh.png b/kallithea/public/images/icons/arrow_refresh.png rename from rhodecode/public/images/icons/arrow_refresh.png rename to kallithea/public/images/icons/arrow_refresh.png diff --git a/rhodecode/public/images/icons/arrow_refresh_small.png b/kallithea/public/images/icons/arrow_refresh_small.png rename from rhodecode/public/images/icons/arrow_refresh_small.png rename to kallithea/public/images/icons/arrow_refresh_small.png diff --git a/rhodecode/public/images/icons/arrow_right.png b/kallithea/public/images/icons/arrow_right.png rename from rhodecode/public/images/icons/arrow_right.png rename to kallithea/public/images/icons/arrow_right.png diff --git a/rhodecode/public/images/icons/arrow_rotate_anticlockwise.png b/kallithea/public/images/icons/arrow_rotate_anticlockwise.png rename from rhodecode/public/images/icons/arrow_rotate_anticlockwise.png rename to kallithea/public/images/icons/arrow_rotate_anticlockwise.png diff --git a/rhodecode/public/images/icons/arrow_rotate_clockwise.png b/kallithea/public/images/icons/arrow_rotate_clockwise.png rename from rhodecode/public/images/icons/arrow_rotate_clockwise.png rename to kallithea/public/images/icons/arrow_rotate_clockwise.png diff --git a/rhodecode/public/images/icons/arrow_switch.png b/kallithea/public/images/icons/arrow_switch.png rename from rhodecode/public/images/icons/arrow_switch.png rename to kallithea/public/images/icons/arrow_switch.png diff --git a/rhodecode/public/images/icons/arrow_turn_left.png b/kallithea/public/images/icons/arrow_turn_left.png rename from rhodecode/public/images/icons/arrow_turn_left.png rename to kallithea/public/images/icons/arrow_turn_left.png diff --git a/rhodecode/public/images/icons/arrow_turn_right.png b/kallithea/public/images/icons/arrow_turn_right.png rename from rhodecode/public/images/icons/arrow_turn_right.png rename to kallithea/public/images/icons/arrow_turn_right.png diff --git a/rhodecode/public/images/icons/arrow_undo.png b/kallithea/public/images/icons/arrow_undo.png rename from rhodecode/public/images/icons/arrow_undo.png rename to kallithea/public/images/icons/arrow_undo.png diff --git a/rhodecode/public/images/icons/arrow_up.png b/kallithea/public/images/icons/arrow_up.png rename from rhodecode/public/images/icons/arrow_up.png rename to kallithea/public/images/icons/arrow_up.png diff --git a/rhodecode/public/images/icons/asterisk_orange.png b/kallithea/public/images/icons/asterisk_orange.png rename from rhodecode/public/images/icons/asterisk_orange.png rename to kallithea/public/images/icons/asterisk_orange.png diff --git a/rhodecode/public/images/icons/asterisk_yellow.png b/kallithea/public/images/icons/asterisk_yellow.png rename from rhodecode/public/images/icons/asterisk_yellow.png rename to kallithea/public/images/icons/asterisk_yellow.png diff --git a/rhodecode/public/images/icons/atom.png b/kallithea/public/images/icons/atom.png rename from rhodecode/public/images/icons/atom.png rename to kallithea/public/images/icons/atom.png diff --git a/rhodecode/public/images/icons/attach.png b/kallithea/public/images/icons/attach.png rename from rhodecode/public/images/icons/attach.png rename to kallithea/public/images/icons/attach.png diff --git a/rhodecode/public/images/icons/award_star_add.png b/kallithea/public/images/icons/award_star_add.png rename from rhodecode/public/images/icons/award_star_add.png rename to kallithea/public/images/icons/award_star_add.png diff --git a/rhodecode/public/images/icons/award_star_bronze_1.png b/kallithea/public/images/icons/award_star_bronze_1.png rename from rhodecode/public/images/icons/award_star_bronze_1.png rename to kallithea/public/images/icons/award_star_bronze_1.png diff --git a/rhodecode/public/images/icons/award_star_bronze_2.png b/kallithea/public/images/icons/award_star_bronze_2.png rename from rhodecode/public/images/icons/award_star_bronze_2.png rename to kallithea/public/images/icons/award_star_bronze_2.png diff --git a/rhodecode/public/images/icons/award_star_bronze_3.png b/kallithea/public/images/icons/award_star_bronze_3.png rename from rhodecode/public/images/icons/award_star_bronze_3.png rename to kallithea/public/images/icons/award_star_bronze_3.png diff --git a/rhodecode/public/images/icons/award_star_delete.png b/kallithea/public/images/icons/award_star_delete.png rename from rhodecode/public/images/icons/award_star_delete.png rename to kallithea/public/images/icons/award_star_delete.png diff --git a/rhodecode/public/images/icons/award_star_gold_1.png b/kallithea/public/images/icons/award_star_gold_1.png rename from rhodecode/public/images/icons/award_star_gold_1.png rename to kallithea/public/images/icons/award_star_gold_1.png diff --git a/rhodecode/public/images/icons/award_star_gold_2.png b/kallithea/public/images/icons/award_star_gold_2.png rename from rhodecode/public/images/icons/award_star_gold_2.png rename to kallithea/public/images/icons/award_star_gold_2.png diff --git a/rhodecode/public/images/icons/award_star_gold_3.png b/kallithea/public/images/icons/award_star_gold_3.png rename from rhodecode/public/images/icons/award_star_gold_3.png rename to kallithea/public/images/icons/award_star_gold_3.png diff --git a/rhodecode/public/images/icons/award_star_silver_1.png b/kallithea/public/images/icons/award_star_silver_1.png rename from rhodecode/public/images/icons/award_star_silver_1.png rename to kallithea/public/images/icons/award_star_silver_1.png diff --git a/rhodecode/public/images/icons/award_star_silver_2.png b/kallithea/public/images/icons/award_star_silver_2.png rename from rhodecode/public/images/icons/award_star_silver_2.png rename to kallithea/public/images/icons/award_star_silver_2.png diff --git a/rhodecode/public/images/icons/award_star_silver_3.png b/kallithea/public/images/icons/award_star_silver_3.png rename from rhodecode/public/images/icons/award_star_silver_3.png rename to kallithea/public/images/icons/award_star_silver_3.png diff --git a/rhodecode/public/images/icons/basket.png b/kallithea/public/images/icons/basket.png rename from rhodecode/public/images/icons/basket.png rename to kallithea/public/images/icons/basket.png diff --git a/rhodecode/public/images/icons/basket_add.png b/kallithea/public/images/icons/basket_add.png rename from rhodecode/public/images/icons/basket_add.png rename to kallithea/public/images/icons/basket_add.png diff --git a/rhodecode/public/images/icons/basket_delete.png b/kallithea/public/images/icons/basket_delete.png rename from rhodecode/public/images/icons/basket_delete.png rename to kallithea/public/images/icons/basket_delete.png diff --git a/rhodecode/public/images/icons/basket_edit.png b/kallithea/public/images/icons/basket_edit.png rename from rhodecode/public/images/icons/basket_edit.png rename to kallithea/public/images/icons/basket_edit.png diff --git a/rhodecode/public/images/icons/basket_error.png b/kallithea/public/images/icons/basket_error.png rename from rhodecode/public/images/icons/basket_error.png rename to kallithea/public/images/icons/basket_error.png diff --git a/rhodecode/public/images/icons/basket_go.png b/kallithea/public/images/icons/basket_go.png rename from rhodecode/public/images/icons/basket_go.png rename to kallithea/public/images/icons/basket_go.png diff --git a/rhodecode/public/images/icons/basket_put.png b/kallithea/public/images/icons/basket_put.png rename from rhodecode/public/images/icons/basket_put.png rename to kallithea/public/images/icons/basket_put.png diff --git a/rhodecode/public/images/icons/basket_remove.png b/kallithea/public/images/icons/basket_remove.png rename from rhodecode/public/images/icons/basket_remove.png rename to kallithea/public/images/icons/basket_remove.png diff --git a/rhodecode/public/images/icons/bell.png b/kallithea/public/images/icons/bell.png rename from rhodecode/public/images/icons/bell.png rename to kallithea/public/images/icons/bell.png diff --git a/rhodecode/public/images/icons/bell_add.png b/kallithea/public/images/icons/bell_add.png rename from rhodecode/public/images/icons/bell_add.png rename to kallithea/public/images/icons/bell_add.png diff --git a/rhodecode/public/images/icons/bell_delete.png b/kallithea/public/images/icons/bell_delete.png rename from rhodecode/public/images/icons/bell_delete.png rename to kallithea/public/images/icons/bell_delete.png diff --git a/rhodecode/public/images/icons/bell_error.png b/kallithea/public/images/icons/bell_error.png rename from rhodecode/public/images/icons/bell_error.png rename to kallithea/public/images/icons/bell_error.png diff --git a/rhodecode/public/images/icons/bell_go.png b/kallithea/public/images/icons/bell_go.png rename from rhodecode/public/images/icons/bell_go.png rename to kallithea/public/images/icons/bell_go.png diff --git a/rhodecode/public/images/icons/bell_link.png b/kallithea/public/images/icons/bell_link.png rename from rhodecode/public/images/icons/bell_link.png rename to kallithea/public/images/icons/bell_link.png diff --git a/rhodecode/public/images/icons/bin.png b/kallithea/public/images/icons/bin.png rename from rhodecode/public/images/icons/bin.png rename to kallithea/public/images/icons/bin.png diff --git a/rhodecode/public/images/icons/bin_closed.png b/kallithea/public/images/icons/bin_closed.png rename from rhodecode/public/images/icons/bin_closed.png rename to kallithea/public/images/icons/bin_closed.png diff --git a/rhodecode/public/images/icons/bin_empty.png b/kallithea/public/images/icons/bin_empty.png rename from rhodecode/public/images/icons/bin_empty.png rename to kallithea/public/images/icons/bin_empty.png diff --git a/rhodecode/public/images/icons/block_16.png b/kallithea/public/images/icons/block_16.png rename from rhodecode/public/images/icons/block_16.png rename to kallithea/public/images/icons/block_16.png diff --git a/rhodecode/public/images/icons/bomb.png b/kallithea/public/images/icons/bomb.png rename from rhodecode/public/images/icons/bomb.png rename to kallithea/public/images/icons/bomb.png diff --git a/rhodecode/public/images/icons/book.png b/kallithea/public/images/icons/book.png rename from rhodecode/public/images/icons/book.png rename to kallithea/public/images/icons/book.png diff --git a/rhodecode/public/images/icons/book_add.png b/kallithea/public/images/icons/book_add.png rename from rhodecode/public/images/icons/book_add.png rename to kallithea/public/images/icons/book_add.png diff --git a/rhodecode/public/images/icons/book_addresses.png b/kallithea/public/images/icons/book_addresses.png rename from rhodecode/public/images/icons/book_addresses.png rename to kallithea/public/images/icons/book_addresses.png diff --git a/rhodecode/public/images/icons/book_delete.png b/kallithea/public/images/icons/book_delete.png rename from rhodecode/public/images/icons/book_delete.png rename to kallithea/public/images/icons/book_delete.png diff --git a/rhodecode/public/images/icons/book_edit.png b/kallithea/public/images/icons/book_edit.png rename from rhodecode/public/images/icons/book_edit.png rename to kallithea/public/images/icons/book_edit.png diff --git a/rhodecode/public/images/icons/book_error.png b/kallithea/public/images/icons/book_error.png rename from rhodecode/public/images/icons/book_error.png rename to kallithea/public/images/icons/book_error.png diff --git a/rhodecode/public/images/icons/book_go.png b/kallithea/public/images/icons/book_go.png rename from rhodecode/public/images/icons/book_go.png rename to kallithea/public/images/icons/book_go.png diff --git a/rhodecode/public/images/icons/book_key.png b/kallithea/public/images/icons/book_key.png rename from rhodecode/public/images/icons/book_key.png rename to kallithea/public/images/icons/book_key.png diff --git a/rhodecode/public/images/icons/book_link.png b/kallithea/public/images/icons/book_link.png rename from rhodecode/public/images/icons/book_link.png rename to kallithea/public/images/icons/book_link.png diff --git a/rhodecode/public/images/icons/book_next.png b/kallithea/public/images/icons/book_next.png rename from rhodecode/public/images/icons/book_next.png rename to kallithea/public/images/icons/book_next.png diff --git a/rhodecode/public/images/icons/book_open.png b/kallithea/public/images/icons/book_open.png rename from rhodecode/public/images/icons/book_open.png rename to kallithea/public/images/icons/book_open.png diff --git a/rhodecode/public/images/icons/book_previous.png b/kallithea/public/images/icons/book_previous.png rename from rhodecode/public/images/icons/book_previous.png rename to kallithea/public/images/icons/book_previous.png diff --git a/rhodecode/public/images/icons/bookmark_16.png b/kallithea/public/images/icons/bookmark_16.png rename from rhodecode/public/images/icons/bookmark_16.png rename to kallithea/public/images/icons/bookmark_16.png diff --git a/rhodecode/public/images/icons/box.png b/kallithea/public/images/icons/box.png rename from rhodecode/public/images/icons/box.png rename to kallithea/public/images/icons/box.png diff --git a/rhodecode/public/images/icons/brick.png b/kallithea/public/images/icons/brick.png rename from rhodecode/public/images/icons/brick.png rename to kallithea/public/images/icons/brick.png diff --git a/rhodecode/public/images/icons/brick_add.png b/kallithea/public/images/icons/brick_add.png rename from rhodecode/public/images/icons/brick_add.png rename to kallithea/public/images/icons/brick_add.png diff --git a/rhodecode/public/images/icons/brick_delete.png b/kallithea/public/images/icons/brick_delete.png rename from rhodecode/public/images/icons/brick_delete.png rename to kallithea/public/images/icons/brick_delete.png diff --git a/rhodecode/public/images/icons/brick_edit.png b/kallithea/public/images/icons/brick_edit.png rename from rhodecode/public/images/icons/brick_edit.png rename to kallithea/public/images/icons/brick_edit.png diff --git a/rhodecode/public/images/icons/brick_error.png b/kallithea/public/images/icons/brick_error.png rename from rhodecode/public/images/icons/brick_error.png rename to kallithea/public/images/icons/brick_error.png diff --git a/rhodecode/public/images/icons/brick_go.png b/kallithea/public/images/icons/brick_go.png rename from rhodecode/public/images/icons/brick_go.png rename to kallithea/public/images/icons/brick_go.png diff --git a/rhodecode/public/images/icons/brick_link.png b/kallithea/public/images/icons/brick_link.png rename from rhodecode/public/images/icons/brick_link.png rename to kallithea/public/images/icons/brick_link.png diff --git a/rhodecode/public/images/icons/bricks.png b/kallithea/public/images/icons/bricks.png rename from rhodecode/public/images/icons/bricks.png rename to kallithea/public/images/icons/bricks.png diff --git a/rhodecode/public/images/icons/briefcase.png b/kallithea/public/images/icons/briefcase.png rename from rhodecode/public/images/icons/briefcase.png rename to kallithea/public/images/icons/briefcase.png diff --git a/rhodecode/public/images/icons/briefcase_16.png b/kallithea/public/images/icons/briefcase_16.png rename from rhodecode/public/images/icons/briefcase_16.png rename to kallithea/public/images/icons/briefcase_16.png diff --git a/rhodecode/public/images/icons/bubble_16.png b/kallithea/public/images/icons/bubble_16.png rename from rhodecode/public/images/icons/bubble_16.png rename to kallithea/public/images/icons/bubble_16.png diff --git a/rhodecode/public/images/icons/bug.png b/kallithea/public/images/icons/bug.png rename from rhodecode/public/images/icons/bug.png rename to kallithea/public/images/icons/bug.png diff --git a/rhodecode/public/images/icons/bug_add.png b/kallithea/public/images/icons/bug_add.png rename from rhodecode/public/images/icons/bug_add.png rename to kallithea/public/images/icons/bug_add.png diff --git a/rhodecode/public/images/icons/bug_delete.png b/kallithea/public/images/icons/bug_delete.png rename from rhodecode/public/images/icons/bug_delete.png rename to kallithea/public/images/icons/bug_delete.png diff --git a/rhodecode/public/images/icons/bug_edit.png b/kallithea/public/images/icons/bug_edit.png rename from rhodecode/public/images/icons/bug_edit.png rename to kallithea/public/images/icons/bug_edit.png diff --git a/rhodecode/public/images/icons/bug_error.png b/kallithea/public/images/icons/bug_error.png rename from rhodecode/public/images/icons/bug_error.png rename to kallithea/public/images/icons/bug_error.png diff --git a/rhodecode/public/images/icons/bug_go.png b/kallithea/public/images/icons/bug_go.png rename from rhodecode/public/images/icons/bug_go.png rename to kallithea/public/images/icons/bug_go.png diff --git a/rhodecode/public/images/icons/bug_link.png b/kallithea/public/images/icons/bug_link.png rename from rhodecode/public/images/icons/bug_link.png rename to kallithea/public/images/icons/bug_link.png diff --git a/rhodecode/public/images/icons/building.png b/kallithea/public/images/icons/building.png rename from rhodecode/public/images/icons/building.png rename to kallithea/public/images/icons/building.png diff --git a/rhodecode/public/images/icons/building_add.png b/kallithea/public/images/icons/building_add.png rename from rhodecode/public/images/icons/building_add.png rename to kallithea/public/images/icons/building_add.png diff --git a/rhodecode/public/images/icons/building_delete.png b/kallithea/public/images/icons/building_delete.png rename from rhodecode/public/images/icons/building_delete.png rename to kallithea/public/images/icons/building_delete.png diff --git a/rhodecode/public/images/icons/building_edit.png b/kallithea/public/images/icons/building_edit.png rename from rhodecode/public/images/icons/building_edit.png rename to kallithea/public/images/icons/building_edit.png diff --git a/rhodecode/public/images/icons/building_error.png b/kallithea/public/images/icons/building_error.png rename from rhodecode/public/images/icons/building_error.png rename to kallithea/public/images/icons/building_error.png diff --git a/rhodecode/public/images/icons/building_go.png b/kallithea/public/images/icons/building_go.png rename from rhodecode/public/images/icons/building_go.png rename to kallithea/public/images/icons/building_go.png diff --git a/rhodecode/public/images/icons/building_key.png b/kallithea/public/images/icons/building_key.png rename from rhodecode/public/images/icons/building_key.png rename to kallithea/public/images/icons/building_key.png diff --git a/rhodecode/public/images/icons/building_link.png b/kallithea/public/images/icons/building_link.png rename from rhodecode/public/images/icons/building_link.png rename to kallithea/public/images/icons/building_link.png diff --git a/rhodecode/public/images/icons/bullet_add.png b/kallithea/public/images/icons/bullet_add.png rename from rhodecode/public/images/icons/bullet_add.png rename to kallithea/public/images/icons/bullet_add.png diff --git a/rhodecode/public/images/icons/bullet_arrow_bottom.png b/kallithea/public/images/icons/bullet_arrow_bottom.png rename from rhodecode/public/images/icons/bullet_arrow_bottom.png rename to kallithea/public/images/icons/bullet_arrow_bottom.png diff --git a/rhodecode/public/images/icons/bullet_arrow_down.png b/kallithea/public/images/icons/bullet_arrow_down.png rename from rhodecode/public/images/icons/bullet_arrow_down.png rename to kallithea/public/images/icons/bullet_arrow_down.png diff --git a/rhodecode/public/images/icons/bullet_arrow_top.png b/kallithea/public/images/icons/bullet_arrow_top.png rename from rhodecode/public/images/icons/bullet_arrow_top.png rename to kallithea/public/images/icons/bullet_arrow_top.png diff --git a/rhodecode/public/images/icons/bullet_arrow_up.png b/kallithea/public/images/icons/bullet_arrow_up.png rename from rhodecode/public/images/icons/bullet_arrow_up.png rename to kallithea/public/images/icons/bullet_arrow_up.png diff --git a/rhodecode/public/images/icons/bullet_black.png b/kallithea/public/images/icons/bullet_black.png rename from rhodecode/public/images/icons/bullet_black.png rename to kallithea/public/images/icons/bullet_black.png diff --git a/rhodecode/public/images/icons/bullet_blue.png b/kallithea/public/images/icons/bullet_blue.png rename from rhodecode/public/images/icons/bullet_blue.png rename to kallithea/public/images/icons/bullet_blue.png diff --git a/rhodecode/public/images/icons/bullet_delete.png b/kallithea/public/images/icons/bullet_delete.png rename from rhodecode/public/images/icons/bullet_delete.png rename to kallithea/public/images/icons/bullet_delete.png diff --git a/rhodecode/public/images/icons/bullet_disk.png b/kallithea/public/images/icons/bullet_disk.png rename from rhodecode/public/images/icons/bullet_disk.png rename to kallithea/public/images/icons/bullet_disk.png diff --git a/rhodecode/public/images/icons/bullet_error.png b/kallithea/public/images/icons/bullet_error.png rename from rhodecode/public/images/icons/bullet_error.png rename to kallithea/public/images/icons/bullet_error.png diff --git a/rhodecode/public/images/icons/bullet_feed.png b/kallithea/public/images/icons/bullet_feed.png rename from rhodecode/public/images/icons/bullet_feed.png rename to kallithea/public/images/icons/bullet_feed.png diff --git a/rhodecode/public/images/icons/bullet_go.png b/kallithea/public/images/icons/bullet_go.png rename from rhodecode/public/images/icons/bullet_go.png rename to kallithea/public/images/icons/bullet_go.png diff --git a/rhodecode/public/images/icons/bullet_green.png b/kallithea/public/images/icons/bullet_green.png rename from rhodecode/public/images/icons/bullet_green.png rename to kallithea/public/images/icons/bullet_green.png diff --git a/rhodecode/public/images/icons/bullet_key.png b/kallithea/public/images/icons/bullet_key.png rename from rhodecode/public/images/icons/bullet_key.png rename to kallithea/public/images/icons/bullet_key.png diff --git a/rhodecode/public/images/icons/bullet_orange.png b/kallithea/public/images/icons/bullet_orange.png rename from rhodecode/public/images/icons/bullet_orange.png rename to kallithea/public/images/icons/bullet_orange.png diff --git a/rhodecode/public/images/icons/bullet_picture.png b/kallithea/public/images/icons/bullet_picture.png rename from rhodecode/public/images/icons/bullet_picture.png rename to kallithea/public/images/icons/bullet_picture.png diff --git a/rhodecode/public/images/icons/bullet_pink.png b/kallithea/public/images/icons/bullet_pink.png rename from rhodecode/public/images/icons/bullet_pink.png rename to kallithea/public/images/icons/bullet_pink.png diff --git a/rhodecode/public/images/icons/bullet_purple.png b/kallithea/public/images/icons/bullet_purple.png rename from rhodecode/public/images/icons/bullet_purple.png rename to kallithea/public/images/icons/bullet_purple.png diff --git a/rhodecode/public/images/icons/bullet_red.png b/kallithea/public/images/icons/bullet_red.png rename from rhodecode/public/images/icons/bullet_red.png rename to kallithea/public/images/icons/bullet_red.png diff --git a/rhodecode/public/images/icons/bullet_star.png b/kallithea/public/images/icons/bullet_star.png rename from rhodecode/public/images/icons/bullet_star.png rename to kallithea/public/images/icons/bullet_star.png diff --git a/rhodecode/public/images/icons/bullet_toggle_minus.png b/kallithea/public/images/icons/bullet_toggle_minus.png rename from rhodecode/public/images/icons/bullet_toggle_minus.png rename to kallithea/public/images/icons/bullet_toggle_minus.png diff --git a/rhodecode/public/images/icons/bullet_toggle_plus.png b/kallithea/public/images/icons/bullet_toggle_plus.png rename from rhodecode/public/images/icons/bullet_toggle_plus.png rename to kallithea/public/images/icons/bullet_toggle_plus.png diff --git a/rhodecode/public/images/icons/bullet_white.png b/kallithea/public/images/icons/bullet_white.png rename from rhodecode/public/images/icons/bullet_white.png rename to kallithea/public/images/icons/bullet_white.png diff --git a/rhodecode/public/images/icons/bullet_wrench.png b/kallithea/public/images/icons/bullet_wrench.png rename from rhodecode/public/images/icons/bullet_wrench.png rename to kallithea/public/images/icons/bullet_wrench.png diff --git a/rhodecode/public/images/icons/bullet_yellow.png b/kallithea/public/images/icons/bullet_yellow.png rename from rhodecode/public/images/icons/bullet_yellow.png rename to kallithea/public/images/icons/bullet_yellow.png diff --git a/rhodecode/public/images/icons/buy_16.png b/kallithea/public/images/icons/buy_16.png rename from rhodecode/public/images/icons/buy_16.png rename to kallithea/public/images/icons/buy_16.png diff --git a/rhodecode/public/images/icons/cake.png b/kallithea/public/images/icons/cake.png rename from rhodecode/public/images/icons/cake.png rename to kallithea/public/images/icons/cake.png diff --git a/rhodecode/public/images/icons/calculator.png b/kallithea/public/images/icons/calculator.png rename from rhodecode/public/images/icons/calculator.png rename to kallithea/public/images/icons/calculator.png diff --git a/rhodecode/public/images/icons/calculator_add.png b/kallithea/public/images/icons/calculator_add.png rename from rhodecode/public/images/icons/calculator_add.png rename to kallithea/public/images/icons/calculator_add.png diff --git a/rhodecode/public/images/icons/calculator_delete.png b/kallithea/public/images/icons/calculator_delete.png rename from rhodecode/public/images/icons/calculator_delete.png rename to kallithea/public/images/icons/calculator_delete.png diff --git a/rhodecode/public/images/icons/calculator_edit.png b/kallithea/public/images/icons/calculator_edit.png rename from rhodecode/public/images/icons/calculator_edit.png rename to kallithea/public/images/icons/calculator_edit.png diff --git a/rhodecode/public/images/icons/calculator_error.png b/kallithea/public/images/icons/calculator_error.png rename from rhodecode/public/images/icons/calculator_error.png rename to kallithea/public/images/icons/calculator_error.png diff --git a/rhodecode/public/images/icons/calculator_link.png b/kallithea/public/images/icons/calculator_link.png rename from rhodecode/public/images/icons/calculator_link.png rename to kallithea/public/images/icons/calculator_link.png diff --git a/rhodecode/public/images/icons/calendar.png b/kallithea/public/images/icons/calendar.png rename from rhodecode/public/images/icons/calendar.png rename to kallithea/public/images/icons/calendar.png diff --git a/rhodecode/public/images/icons/calendar_16.png b/kallithea/public/images/icons/calendar_16.png rename from rhodecode/public/images/icons/calendar_16.png rename to kallithea/public/images/icons/calendar_16.png diff --git a/rhodecode/public/images/icons/calendar_add.png b/kallithea/public/images/icons/calendar_add.png rename from rhodecode/public/images/icons/calendar_add.png rename to kallithea/public/images/icons/calendar_add.png diff --git a/rhodecode/public/images/icons/calendar_delete.png b/kallithea/public/images/icons/calendar_delete.png rename from rhodecode/public/images/icons/calendar_delete.png rename to kallithea/public/images/icons/calendar_delete.png diff --git a/rhodecode/public/images/icons/calendar_edit.png b/kallithea/public/images/icons/calendar_edit.png rename from rhodecode/public/images/icons/calendar_edit.png rename to kallithea/public/images/icons/calendar_edit.png diff --git a/rhodecode/public/images/icons/calendar_link.png b/kallithea/public/images/icons/calendar_link.png rename from rhodecode/public/images/icons/calendar_link.png rename to kallithea/public/images/icons/calendar_link.png diff --git a/rhodecode/public/images/icons/calendar_view_day.png b/kallithea/public/images/icons/calendar_view_day.png rename from rhodecode/public/images/icons/calendar_view_day.png rename to kallithea/public/images/icons/calendar_view_day.png diff --git a/rhodecode/public/images/icons/calendar_view_month.png b/kallithea/public/images/icons/calendar_view_month.png rename from rhodecode/public/images/icons/calendar_view_month.png rename to kallithea/public/images/icons/calendar_view_month.png diff --git a/rhodecode/public/images/icons/calendar_view_week.png b/kallithea/public/images/icons/calendar_view_week.png rename from rhodecode/public/images/icons/calendar_view_week.png rename to kallithea/public/images/icons/calendar_view_week.png diff --git a/rhodecode/public/images/icons/camera.png b/kallithea/public/images/icons/camera.png rename from rhodecode/public/images/icons/camera.png rename to kallithea/public/images/icons/camera.png diff --git a/rhodecode/public/images/icons/camera_add.png b/kallithea/public/images/icons/camera_add.png rename from rhodecode/public/images/icons/camera_add.png rename to kallithea/public/images/icons/camera_add.png diff --git a/rhodecode/public/images/icons/camera_delete.png b/kallithea/public/images/icons/camera_delete.png rename from rhodecode/public/images/icons/camera_delete.png rename to kallithea/public/images/icons/camera_delete.png diff --git a/rhodecode/public/images/icons/camera_edit.png b/kallithea/public/images/icons/camera_edit.png rename from rhodecode/public/images/icons/camera_edit.png rename to kallithea/public/images/icons/camera_edit.png diff --git a/rhodecode/public/images/icons/camera_error.png b/kallithea/public/images/icons/camera_error.png rename from rhodecode/public/images/icons/camera_error.png rename to kallithea/public/images/icons/camera_error.png diff --git a/rhodecode/public/images/icons/camera_go.png b/kallithea/public/images/icons/camera_go.png rename from rhodecode/public/images/icons/camera_go.png rename to kallithea/public/images/icons/camera_go.png diff --git a/rhodecode/public/images/icons/camera_link.png b/kallithea/public/images/icons/camera_link.png rename from rhodecode/public/images/icons/camera_link.png rename to kallithea/public/images/icons/camera_link.png diff --git a/rhodecode/public/images/icons/camera_small.png b/kallithea/public/images/icons/camera_small.png rename from rhodecode/public/images/icons/camera_small.png rename to kallithea/public/images/icons/camera_small.png diff --git a/rhodecode/public/images/icons/cancel.png b/kallithea/public/images/icons/cancel.png rename from rhodecode/public/images/icons/cancel.png rename to kallithea/public/images/icons/cancel.png diff --git a/rhodecode/public/images/icons/car.png b/kallithea/public/images/icons/car.png rename from rhodecode/public/images/icons/car.png rename to kallithea/public/images/icons/car.png diff --git a/rhodecode/public/images/icons/car_add.png b/kallithea/public/images/icons/car_add.png rename from rhodecode/public/images/icons/car_add.png rename to kallithea/public/images/icons/car_add.png diff --git a/rhodecode/public/images/icons/car_delete.png b/kallithea/public/images/icons/car_delete.png rename from rhodecode/public/images/icons/car_delete.png rename to kallithea/public/images/icons/car_delete.png diff --git a/rhodecode/public/images/icons/cart.png b/kallithea/public/images/icons/cart.png rename from rhodecode/public/images/icons/cart.png rename to kallithea/public/images/icons/cart.png diff --git a/rhodecode/public/images/icons/cart_add.png b/kallithea/public/images/icons/cart_add.png rename from rhodecode/public/images/icons/cart_add.png rename to kallithea/public/images/icons/cart_add.png diff --git a/rhodecode/public/images/icons/cart_delete.png b/kallithea/public/images/icons/cart_delete.png rename from rhodecode/public/images/icons/cart_delete.png rename to kallithea/public/images/icons/cart_delete.png diff --git a/rhodecode/public/images/icons/cart_edit.png b/kallithea/public/images/icons/cart_edit.png rename from rhodecode/public/images/icons/cart_edit.png rename to kallithea/public/images/icons/cart_edit.png diff --git a/rhodecode/public/images/icons/cart_error.png b/kallithea/public/images/icons/cart_error.png rename from rhodecode/public/images/icons/cart_error.png rename to kallithea/public/images/icons/cart_error.png diff --git a/rhodecode/public/images/icons/cart_go.png b/kallithea/public/images/icons/cart_go.png rename from rhodecode/public/images/icons/cart_go.png rename to kallithea/public/images/icons/cart_go.png diff --git a/rhodecode/public/images/icons/cart_put.png b/kallithea/public/images/icons/cart_put.png rename from rhodecode/public/images/icons/cart_put.png rename to kallithea/public/images/icons/cart_put.png diff --git a/rhodecode/public/images/icons/cart_remove.png b/kallithea/public/images/icons/cart_remove.png rename from rhodecode/public/images/icons/cart_remove.png rename to kallithea/public/images/icons/cart_remove.png diff --git a/rhodecode/public/images/icons/cd.png b/kallithea/public/images/icons/cd.png rename from rhodecode/public/images/icons/cd.png rename to kallithea/public/images/icons/cd.png diff --git a/rhodecode/public/images/icons/cd_add.png b/kallithea/public/images/icons/cd_add.png rename from rhodecode/public/images/icons/cd_add.png rename to kallithea/public/images/icons/cd_add.png diff --git a/rhodecode/public/images/icons/cd_burn.png b/kallithea/public/images/icons/cd_burn.png rename from rhodecode/public/images/icons/cd_burn.png rename to kallithea/public/images/icons/cd_burn.png diff --git a/rhodecode/public/images/icons/cd_delete.png b/kallithea/public/images/icons/cd_delete.png rename from rhodecode/public/images/icons/cd_delete.png rename to kallithea/public/images/icons/cd_delete.png diff --git a/rhodecode/public/images/icons/cd_edit.png b/kallithea/public/images/icons/cd_edit.png rename from rhodecode/public/images/icons/cd_edit.png rename to kallithea/public/images/icons/cd_edit.png diff --git a/rhodecode/public/images/icons/cd_eject.png b/kallithea/public/images/icons/cd_eject.png rename from rhodecode/public/images/icons/cd_eject.png rename to kallithea/public/images/icons/cd_eject.png diff --git a/rhodecode/public/images/icons/cd_go.png b/kallithea/public/images/icons/cd_go.png rename from rhodecode/public/images/icons/cd_go.png rename to kallithea/public/images/icons/cd_go.png diff --git a/rhodecode/public/images/icons/chart_bar.png b/kallithea/public/images/icons/chart_bar.png rename from rhodecode/public/images/icons/chart_bar.png rename to kallithea/public/images/icons/chart_bar.png diff --git a/rhodecode/public/images/icons/chart_bar_add.png b/kallithea/public/images/icons/chart_bar_add.png rename from rhodecode/public/images/icons/chart_bar_add.png rename to kallithea/public/images/icons/chart_bar_add.png diff --git a/rhodecode/public/images/icons/chart_bar_delete.png b/kallithea/public/images/icons/chart_bar_delete.png rename from rhodecode/public/images/icons/chart_bar_delete.png rename to kallithea/public/images/icons/chart_bar_delete.png diff --git a/rhodecode/public/images/icons/chart_bar_edit.png b/kallithea/public/images/icons/chart_bar_edit.png rename from rhodecode/public/images/icons/chart_bar_edit.png rename to kallithea/public/images/icons/chart_bar_edit.png diff --git a/rhodecode/public/images/icons/chart_bar_error.png b/kallithea/public/images/icons/chart_bar_error.png rename from rhodecode/public/images/icons/chart_bar_error.png rename to kallithea/public/images/icons/chart_bar_error.png diff --git a/rhodecode/public/images/icons/chart_bar_link.png b/kallithea/public/images/icons/chart_bar_link.png rename from rhodecode/public/images/icons/chart_bar_link.png rename to kallithea/public/images/icons/chart_bar_link.png diff --git a/rhodecode/public/images/icons/chart_curve.png b/kallithea/public/images/icons/chart_curve.png rename from rhodecode/public/images/icons/chart_curve.png rename to kallithea/public/images/icons/chart_curve.png diff --git a/rhodecode/public/images/icons/chart_curve_add.png b/kallithea/public/images/icons/chart_curve_add.png rename from rhodecode/public/images/icons/chart_curve_add.png rename to kallithea/public/images/icons/chart_curve_add.png diff --git a/rhodecode/public/images/icons/chart_curve_delete.png b/kallithea/public/images/icons/chart_curve_delete.png rename from rhodecode/public/images/icons/chart_curve_delete.png rename to kallithea/public/images/icons/chart_curve_delete.png diff --git a/rhodecode/public/images/icons/chart_curve_edit.png b/kallithea/public/images/icons/chart_curve_edit.png rename from rhodecode/public/images/icons/chart_curve_edit.png rename to kallithea/public/images/icons/chart_curve_edit.png diff --git a/rhodecode/public/images/icons/chart_curve_error.png b/kallithea/public/images/icons/chart_curve_error.png rename from rhodecode/public/images/icons/chart_curve_error.png rename to kallithea/public/images/icons/chart_curve_error.png diff --git a/rhodecode/public/images/icons/chart_curve_go.png b/kallithea/public/images/icons/chart_curve_go.png rename from rhodecode/public/images/icons/chart_curve_go.png rename to kallithea/public/images/icons/chart_curve_go.png diff --git a/rhodecode/public/images/icons/chart_curve_link.png b/kallithea/public/images/icons/chart_curve_link.png rename from rhodecode/public/images/icons/chart_curve_link.png rename to kallithea/public/images/icons/chart_curve_link.png diff --git a/rhodecode/public/images/icons/chart_line.png b/kallithea/public/images/icons/chart_line.png rename from rhodecode/public/images/icons/chart_line.png rename to kallithea/public/images/icons/chart_line.png diff --git a/rhodecode/public/images/icons/chart_line_add.png b/kallithea/public/images/icons/chart_line_add.png rename from rhodecode/public/images/icons/chart_line_add.png rename to kallithea/public/images/icons/chart_line_add.png diff --git a/rhodecode/public/images/icons/chart_line_delete.png b/kallithea/public/images/icons/chart_line_delete.png rename from rhodecode/public/images/icons/chart_line_delete.png rename to kallithea/public/images/icons/chart_line_delete.png diff --git a/rhodecode/public/images/icons/chart_line_edit.png b/kallithea/public/images/icons/chart_line_edit.png rename from rhodecode/public/images/icons/chart_line_edit.png rename to kallithea/public/images/icons/chart_line_edit.png diff --git a/rhodecode/public/images/icons/chart_line_error.png b/kallithea/public/images/icons/chart_line_error.png rename from rhodecode/public/images/icons/chart_line_error.png rename to kallithea/public/images/icons/chart_line_error.png diff --git a/rhodecode/public/images/icons/chart_line_link.png b/kallithea/public/images/icons/chart_line_link.png rename from rhodecode/public/images/icons/chart_line_link.png rename to kallithea/public/images/icons/chart_line_link.png diff --git a/rhodecode/public/images/icons/chart_organisation.png b/kallithea/public/images/icons/chart_organisation.png rename from rhodecode/public/images/icons/chart_organisation.png rename to kallithea/public/images/icons/chart_organisation.png diff --git a/rhodecode/public/images/icons/chart_organisation_add.png b/kallithea/public/images/icons/chart_organisation_add.png rename from rhodecode/public/images/icons/chart_organisation_add.png rename to kallithea/public/images/icons/chart_organisation_add.png diff --git a/rhodecode/public/images/icons/chart_organisation_delete.png b/kallithea/public/images/icons/chart_organisation_delete.png rename from rhodecode/public/images/icons/chart_organisation_delete.png rename to kallithea/public/images/icons/chart_organisation_delete.png diff --git a/rhodecode/public/images/icons/chart_pie.png b/kallithea/public/images/icons/chart_pie.png rename from rhodecode/public/images/icons/chart_pie.png rename to kallithea/public/images/icons/chart_pie.png diff --git a/rhodecode/public/images/icons/chart_pie_add.png b/kallithea/public/images/icons/chart_pie_add.png rename from rhodecode/public/images/icons/chart_pie_add.png rename to kallithea/public/images/icons/chart_pie_add.png diff --git a/rhodecode/public/images/icons/chart_pie_delete.png b/kallithea/public/images/icons/chart_pie_delete.png rename from rhodecode/public/images/icons/chart_pie_delete.png rename to kallithea/public/images/icons/chart_pie_delete.png diff --git a/rhodecode/public/images/icons/chart_pie_edit.png b/kallithea/public/images/icons/chart_pie_edit.png rename from rhodecode/public/images/icons/chart_pie_edit.png rename to kallithea/public/images/icons/chart_pie_edit.png diff --git a/rhodecode/public/images/icons/chart_pie_error.png b/kallithea/public/images/icons/chart_pie_error.png rename from rhodecode/public/images/icons/chart_pie_error.png rename to kallithea/public/images/icons/chart_pie_error.png diff --git a/rhodecode/public/images/icons/chart_pie_link.png b/kallithea/public/images/icons/chart_pie_link.png rename from rhodecode/public/images/icons/chart_pie_link.png rename to kallithea/public/images/icons/chart_pie_link.png diff --git a/rhodecode/public/images/icons/clipboard_16.png b/kallithea/public/images/icons/clipboard_16.png rename from rhodecode/public/images/icons/clipboard_16.png rename to kallithea/public/images/icons/clipboard_16.png diff --git a/rhodecode/public/images/icons/clock.png b/kallithea/public/images/icons/clock.png rename from rhodecode/public/images/icons/clock.png rename to kallithea/public/images/icons/clock.png diff --git a/rhodecode/public/images/icons/clock_16.png b/kallithea/public/images/icons/clock_16.png rename from rhodecode/public/images/icons/clock_16.png rename to kallithea/public/images/icons/clock_16.png diff --git a/rhodecode/public/images/icons/clock_add.png b/kallithea/public/images/icons/clock_add.png rename from rhodecode/public/images/icons/clock_add.png rename to kallithea/public/images/icons/clock_add.png diff --git a/rhodecode/public/images/icons/clock_delete.png b/kallithea/public/images/icons/clock_delete.png rename from rhodecode/public/images/icons/clock_delete.png rename to kallithea/public/images/icons/clock_delete.png diff --git a/rhodecode/public/images/icons/clock_edit.png b/kallithea/public/images/icons/clock_edit.png rename from rhodecode/public/images/icons/clock_edit.png rename to kallithea/public/images/icons/clock_edit.png diff --git a/rhodecode/public/images/icons/clock_error.png b/kallithea/public/images/icons/clock_error.png rename from rhodecode/public/images/icons/clock_error.png rename to kallithea/public/images/icons/clock_error.png diff --git a/rhodecode/public/images/icons/clock_go.png b/kallithea/public/images/icons/clock_go.png rename from rhodecode/public/images/icons/clock_go.png rename to kallithea/public/images/icons/clock_go.png diff --git a/rhodecode/public/images/icons/clock_link.png b/kallithea/public/images/icons/clock_link.png rename from rhodecode/public/images/icons/clock_link.png rename to kallithea/public/images/icons/clock_link.png diff --git a/rhodecode/public/images/icons/clock_pause.png b/kallithea/public/images/icons/clock_pause.png rename from rhodecode/public/images/icons/clock_pause.png rename to kallithea/public/images/icons/clock_pause.png diff --git a/rhodecode/public/images/icons/clock_play.png b/kallithea/public/images/icons/clock_play.png rename from rhodecode/public/images/icons/clock_play.png rename to kallithea/public/images/icons/clock_play.png diff --git a/rhodecode/public/images/icons/clock_red.png b/kallithea/public/images/icons/clock_red.png rename from rhodecode/public/images/icons/clock_red.png rename to kallithea/public/images/icons/clock_red.png diff --git a/rhodecode/public/images/icons/clock_stop.png b/kallithea/public/images/icons/clock_stop.png rename from rhodecode/public/images/icons/clock_stop.png rename to kallithea/public/images/icons/clock_stop.png diff --git a/rhodecode/public/images/icons/cog.png b/kallithea/public/images/icons/cog.png rename from rhodecode/public/images/icons/cog.png rename to kallithea/public/images/icons/cog.png diff --git a/rhodecode/public/images/icons/cog_add.png b/kallithea/public/images/icons/cog_add.png rename from rhodecode/public/images/icons/cog_add.png rename to kallithea/public/images/icons/cog_add.png diff --git a/rhodecode/public/images/icons/cog_delete.png b/kallithea/public/images/icons/cog_delete.png rename from rhodecode/public/images/icons/cog_delete.png rename to kallithea/public/images/icons/cog_delete.png diff --git a/rhodecode/public/images/icons/cog_edit.png b/kallithea/public/images/icons/cog_edit.png rename from rhodecode/public/images/icons/cog_edit.png rename to kallithea/public/images/icons/cog_edit.png diff --git a/rhodecode/public/images/icons/cog_error.png b/kallithea/public/images/icons/cog_error.png rename from rhodecode/public/images/icons/cog_error.png rename to kallithea/public/images/icons/cog_error.png diff --git a/rhodecode/public/images/icons/cog_go.png b/kallithea/public/images/icons/cog_go.png rename from rhodecode/public/images/icons/cog_go.png rename to kallithea/public/images/icons/cog_go.png diff --git a/rhodecode/public/images/icons/coins.png b/kallithea/public/images/icons/coins.png rename from rhodecode/public/images/icons/coins.png rename to kallithea/public/images/icons/coins.png diff --git a/rhodecode/public/images/icons/coins_add.png b/kallithea/public/images/icons/coins_add.png rename from rhodecode/public/images/icons/coins_add.png rename to kallithea/public/images/icons/coins_add.png diff --git a/rhodecode/public/images/icons/coins_delete.png b/kallithea/public/images/icons/coins_delete.png rename from rhodecode/public/images/icons/coins_delete.png rename to kallithea/public/images/icons/coins_delete.png diff --git a/rhodecode/public/images/icons/color_swatch.png b/kallithea/public/images/icons/color_swatch.png rename from rhodecode/public/images/icons/color_swatch.png rename to kallithea/public/images/icons/color_swatch.png diff --git a/rhodecode/public/images/icons/color_wheel.png b/kallithea/public/images/icons/color_wheel.png rename from rhodecode/public/images/icons/color_wheel.png rename to kallithea/public/images/icons/color_wheel.png diff --git a/rhodecode/public/images/icons/comment.png b/kallithea/public/images/icons/comment.png rename from rhodecode/public/images/icons/comment.png rename to kallithea/public/images/icons/comment.png diff --git a/rhodecode/public/images/icons/comment_add.png b/kallithea/public/images/icons/comment_add.png rename from rhodecode/public/images/icons/comment_add.png rename to kallithea/public/images/icons/comment_add.png diff --git a/rhodecode/public/images/icons/comment_delete.png b/kallithea/public/images/icons/comment_delete.png rename from rhodecode/public/images/icons/comment_delete.png rename to kallithea/public/images/icons/comment_delete.png diff --git a/rhodecode/public/images/icons/comment_edit.png b/kallithea/public/images/icons/comment_edit.png rename from rhodecode/public/images/icons/comment_edit.png rename to kallithea/public/images/icons/comment_edit.png diff --git a/rhodecode/public/images/icons/comments.png b/kallithea/public/images/icons/comments.png rename from rhodecode/public/images/icons/comments.png rename to kallithea/public/images/icons/comments.png diff --git a/rhodecode/public/images/icons/comments_add.png b/kallithea/public/images/icons/comments_add.png rename from rhodecode/public/images/icons/comments_add.png rename to kallithea/public/images/icons/comments_add.png diff --git a/rhodecode/public/images/icons/comments_delete.png b/kallithea/public/images/icons/comments_delete.png rename from rhodecode/public/images/icons/comments_delete.png rename to kallithea/public/images/icons/comments_delete.png diff --git a/rhodecode/public/images/icons/compress.png b/kallithea/public/images/icons/compress.png rename from rhodecode/public/images/icons/compress.png rename to kallithea/public/images/icons/compress.png diff --git a/rhodecode/public/images/icons/computer.png b/kallithea/public/images/icons/computer.png rename from rhodecode/public/images/icons/computer.png rename to kallithea/public/images/icons/computer.png diff --git a/rhodecode/public/images/icons/computer_add.png b/kallithea/public/images/icons/computer_add.png rename from rhodecode/public/images/icons/computer_add.png rename to kallithea/public/images/icons/computer_add.png diff --git a/rhodecode/public/images/icons/computer_delete.png b/kallithea/public/images/icons/computer_delete.png rename from rhodecode/public/images/icons/computer_delete.png rename to kallithea/public/images/icons/computer_delete.png diff --git a/rhodecode/public/images/icons/computer_edit.png b/kallithea/public/images/icons/computer_edit.png rename from rhodecode/public/images/icons/computer_edit.png rename to kallithea/public/images/icons/computer_edit.png diff --git a/rhodecode/public/images/icons/computer_error.png b/kallithea/public/images/icons/computer_error.png rename from rhodecode/public/images/icons/computer_error.png rename to kallithea/public/images/icons/computer_error.png diff --git a/rhodecode/public/images/icons/computer_go.png b/kallithea/public/images/icons/computer_go.png rename from rhodecode/public/images/icons/computer_go.png rename to kallithea/public/images/icons/computer_go.png diff --git a/rhodecode/public/images/icons/computer_key.png b/kallithea/public/images/icons/computer_key.png rename from rhodecode/public/images/icons/computer_key.png rename to kallithea/public/images/icons/computer_key.png diff --git a/rhodecode/public/images/icons/computer_link.png b/kallithea/public/images/icons/computer_link.png rename from rhodecode/public/images/icons/computer_link.png rename to kallithea/public/images/icons/computer_link.png diff --git a/rhodecode/public/images/icons/connect.png b/kallithea/public/images/icons/connect.png rename from rhodecode/public/images/icons/connect.png rename to kallithea/public/images/icons/connect.png diff --git a/rhodecode/public/images/icons/contrast.png b/kallithea/public/images/icons/contrast.png rename from rhodecode/public/images/icons/contrast.png rename to kallithea/public/images/icons/contrast.png diff --git a/rhodecode/public/images/icons/contrast_decrease.png b/kallithea/public/images/icons/contrast_decrease.png rename from rhodecode/public/images/icons/contrast_decrease.png rename to kallithea/public/images/icons/contrast_decrease.png diff --git a/rhodecode/public/images/icons/contrast_high.png b/kallithea/public/images/icons/contrast_high.png rename from rhodecode/public/images/icons/contrast_high.png rename to kallithea/public/images/icons/contrast_high.png diff --git a/rhodecode/public/images/icons/contrast_increase.png b/kallithea/public/images/icons/contrast_increase.png rename from rhodecode/public/images/icons/contrast_increase.png rename to kallithea/public/images/icons/contrast_increase.png diff --git a/rhodecode/public/images/icons/contrast_low.png b/kallithea/public/images/icons/contrast_low.png rename from rhodecode/public/images/icons/contrast_low.png rename to kallithea/public/images/icons/contrast_low.png diff --git a/rhodecode/public/images/icons/control_eject.png b/kallithea/public/images/icons/control_eject.png rename from rhodecode/public/images/icons/control_eject.png rename to kallithea/public/images/icons/control_eject.png diff --git a/rhodecode/public/images/icons/control_eject_blue.png b/kallithea/public/images/icons/control_eject_blue.png rename from rhodecode/public/images/icons/control_eject_blue.png rename to kallithea/public/images/icons/control_eject_blue.png diff --git a/rhodecode/public/images/icons/control_end.png b/kallithea/public/images/icons/control_end.png rename from rhodecode/public/images/icons/control_end.png rename to kallithea/public/images/icons/control_end.png diff --git a/rhodecode/public/images/icons/control_end_blue.png b/kallithea/public/images/icons/control_end_blue.png rename from rhodecode/public/images/icons/control_end_blue.png rename to kallithea/public/images/icons/control_end_blue.png diff --git a/rhodecode/public/images/icons/control_equalizer.png b/kallithea/public/images/icons/control_equalizer.png rename from rhodecode/public/images/icons/control_equalizer.png rename to kallithea/public/images/icons/control_equalizer.png diff --git a/rhodecode/public/images/icons/control_equalizer_blue.png b/kallithea/public/images/icons/control_equalizer_blue.png rename from rhodecode/public/images/icons/control_equalizer_blue.png rename to kallithea/public/images/icons/control_equalizer_blue.png diff --git a/rhodecode/public/images/icons/control_fastforward.png b/kallithea/public/images/icons/control_fastforward.png rename from rhodecode/public/images/icons/control_fastforward.png rename to kallithea/public/images/icons/control_fastforward.png diff --git a/rhodecode/public/images/icons/control_fastforward_blue.png b/kallithea/public/images/icons/control_fastforward_blue.png rename from rhodecode/public/images/icons/control_fastforward_blue.png rename to kallithea/public/images/icons/control_fastforward_blue.png diff --git a/rhodecode/public/images/icons/control_pause.png b/kallithea/public/images/icons/control_pause.png rename from rhodecode/public/images/icons/control_pause.png rename to kallithea/public/images/icons/control_pause.png diff --git a/rhodecode/public/images/icons/control_pause_blue.png b/kallithea/public/images/icons/control_pause_blue.png rename from rhodecode/public/images/icons/control_pause_blue.png rename to kallithea/public/images/icons/control_pause_blue.png diff --git a/rhodecode/public/images/icons/control_play.png b/kallithea/public/images/icons/control_play.png rename from rhodecode/public/images/icons/control_play.png rename to kallithea/public/images/icons/control_play.png diff --git a/rhodecode/public/images/icons/control_play_blue.png b/kallithea/public/images/icons/control_play_blue.png rename from rhodecode/public/images/icons/control_play_blue.png rename to kallithea/public/images/icons/control_play_blue.png diff --git a/rhodecode/public/images/icons/control_repeat.png b/kallithea/public/images/icons/control_repeat.png rename from rhodecode/public/images/icons/control_repeat.png rename to kallithea/public/images/icons/control_repeat.png diff --git a/rhodecode/public/images/icons/control_repeat_blue.png b/kallithea/public/images/icons/control_repeat_blue.png rename from rhodecode/public/images/icons/control_repeat_blue.png rename to kallithea/public/images/icons/control_repeat_blue.png diff --git a/rhodecode/public/images/icons/control_rewind.png b/kallithea/public/images/icons/control_rewind.png rename from rhodecode/public/images/icons/control_rewind.png rename to kallithea/public/images/icons/control_rewind.png diff --git a/rhodecode/public/images/icons/control_rewind_blue.png b/kallithea/public/images/icons/control_rewind_blue.png rename from rhodecode/public/images/icons/control_rewind_blue.png rename to kallithea/public/images/icons/control_rewind_blue.png diff --git a/rhodecode/public/images/icons/control_start.png b/kallithea/public/images/icons/control_start.png rename from rhodecode/public/images/icons/control_start.png rename to kallithea/public/images/icons/control_start.png diff --git a/rhodecode/public/images/icons/control_start_blue.png b/kallithea/public/images/icons/control_start_blue.png rename from rhodecode/public/images/icons/control_start_blue.png rename to kallithea/public/images/icons/control_start_blue.png diff --git a/rhodecode/public/images/icons/control_stop.png b/kallithea/public/images/icons/control_stop.png rename from rhodecode/public/images/icons/control_stop.png rename to kallithea/public/images/icons/control_stop.png diff --git a/rhodecode/public/images/icons/control_stop_blue.png b/kallithea/public/images/icons/control_stop_blue.png rename from rhodecode/public/images/icons/control_stop_blue.png rename to kallithea/public/images/icons/control_stop_blue.png diff --git a/rhodecode/public/images/icons/controller.png b/kallithea/public/images/icons/controller.png rename from rhodecode/public/images/icons/controller.png rename to kallithea/public/images/icons/controller.png diff --git a/rhodecode/public/images/icons/controller_add.png b/kallithea/public/images/icons/controller_add.png rename from rhodecode/public/images/icons/controller_add.png rename to kallithea/public/images/icons/controller_add.png diff --git a/rhodecode/public/images/icons/controller_delete.png b/kallithea/public/images/icons/controller_delete.png rename from rhodecode/public/images/icons/controller_delete.png rename to kallithea/public/images/icons/controller_delete.png diff --git a/rhodecode/public/images/icons/controller_error.png b/kallithea/public/images/icons/controller_error.png rename from rhodecode/public/images/icons/controller_error.png rename to kallithea/public/images/icons/controller_error.png diff --git a/rhodecode/public/images/icons/creditcards.png b/kallithea/public/images/icons/creditcards.png rename from rhodecode/public/images/icons/creditcards.png rename to kallithea/public/images/icons/creditcards.png diff --git a/rhodecode/public/images/icons/cross.png b/kallithea/public/images/icons/cross.png rename from rhodecode/public/images/icons/cross.png rename to kallithea/public/images/icons/cross.png diff --git a/rhodecode/public/images/icons/css.png b/kallithea/public/images/icons/css.png rename from rhodecode/public/images/icons/css.png rename to kallithea/public/images/icons/css.png diff --git a/rhodecode/public/images/icons/css_add.png b/kallithea/public/images/icons/css_add.png rename from rhodecode/public/images/icons/css_add.png rename to kallithea/public/images/icons/css_add.png diff --git a/rhodecode/public/images/icons/css_delete.png b/kallithea/public/images/icons/css_delete.png rename from rhodecode/public/images/icons/css_delete.png rename to kallithea/public/images/icons/css_delete.png diff --git a/rhodecode/public/images/icons/css_go.png b/kallithea/public/images/icons/css_go.png rename from rhodecode/public/images/icons/css_go.png rename to kallithea/public/images/icons/css_go.png diff --git a/rhodecode/public/images/icons/css_valid.png b/kallithea/public/images/icons/css_valid.png rename from rhodecode/public/images/icons/css_valid.png rename to kallithea/public/images/icons/css_valid.png diff --git a/rhodecode/public/images/icons/cup.png b/kallithea/public/images/icons/cup.png rename from rhodecode/public/images/icons/cup.png rename to kallithea/public/images/icons/cup.png diff --git a/rhodecode/public/images/icons/cup_add.png b/kallithea/public/images/icons/cup_add.png rename from rhodecode/public/images/icons/cup_add.png rename to kallithea/public/images/icons/cup_add.png diff --git a/rhodecode/public/images/icons/cup_delete.png b/kallithea/public/images/icons/cup_delete.png rename from rhodecode/public/images/icons/cup_delete.png rename to kallithea/public/images/icons/cup_delete.png diff --git a/rhodecode/public/images/icons/cup_edit.png b/kallithea/public/images/icons/cup_edit.png rename from rhodecode/public/images/icons/cup_edit.png rename to kallithea/public/images/icons/cup_edit.png diff --git a/rhodecode/public/images/icons/cup_error.png b/kallithea/public/images/icons/cup_error.png rename from rhodecode/public/images/icons/cup_error.png rename to kallithea/public/images/icons/cup_error.png diff --git a/rhodecode/public/images/icons/cup_go.png b/kallithea/public/images/icons/cup_go.png rename from rhodecode/public/images/icons/cup_go.png rename to kallithea/public/images/icons/cup_go.png diff --git a/rhodecode/public/images/icons/cup_key.png b/kallithea/public/images/icons/cup_key.png rename from rhodecode/public/images/icons/cup_key.png rename to kallithea/public/images/icons/cup_key.png diff --git a/rhodecode/public/images/icons/cup_link.png b/kallithea/public/images/icons/cup_link.png rename from rhodecode/public/images/icons/cup_link.png rename to kallithea/public/images/icons/cup_link.png diff --git a/rhodecode/public/images/icons/cursor.png b/kallithea/public/images/icons/cursor.png rename from rhodecode/public/images/icons/cursor.png rename to kallithea/public/images/icons/cursor.png diff --git a/rhodecode/public/images/icons/cut.png b/kallithea/public/images/icons/cut.png rename from rhodecode/public/images/icons/cut.png rename to kallithea/public/images/icons/cut.png diff --git a/rhodecode/public/images/icons/cut_red.png b/kallithea/public/images/icons/cut_red.png rename from rhodecode/public/images/icons/cut_red.png rename to kallithea/public/images/icons/cut_red.png diff --git a/rhodecode/public/images/icons/database.png b/kallithea/public/images/icons/database.png rename from rhodecode/public/images/icons/database.png rename to kallithea/public/images/icons/database.png diff --git a/rhodecode/public/images/icons/database_add.png b/kallithea/public/images/icons/database_add.png rename from rhodecode/public/images/icons/database_add.png rename to kallithea/public/images/icons/database_add.png diff --git a/rhodecode/public/images/icons/database_connect.png b/kallithea/public/images/icons/database_connect.png rename from rhodecode/public/images/icons/database_connect.png rename to kallithea/public/images/icons/database_connect.png diff --git a/rhodecode/public/images/icons/database_delete.png b/kallithea/public/images/icons/database_delete.png rename from rhodecode/public/images/icons/database_delete.png rename to kallithea/public/images/icons/database_delete.png diff --git a/rhodecode/public/images/icons/database_edit.png b/kallithea/public/images/icons/database_edit.png rename from rhodecode/public/images/icons/database_edit.png rename to kallithea/public/images/icons/database_edit.png diff --git a/rhodecode/public/images/icons/database_error.png b/kallithea/public/images/icons/database_error.png rename from rhodecode/public/images/icons/database_error.png rename to kallithea/public/images/icons/database_error.png diff --git a/rhodecode/public/images/icons/database_gear.png b/kallithea/public/images/icons/database_gear.png rename from rhodecode/public/images/icons/database_gear.png rename to kallithea/public/images/icons/database_gear.png diff --git a/rhodecode/public/images/icons/database_go.png b/kallithea/public/images/icons/database_go.png rename from rhodecode/public/images/icons/database_go.png rename to kallithea/public/images/icons/database_go.png diff --git a/rhodecode/public/images/icons/database_key.png b/kallithea/public/images/icons/database_key.png rename from rhodecode/public/images/icons/database_key.png rename to kallithea/public/images/icons/database_key.png diff --git a/rhodecode/public/images/icons/database_lightning.png b/kallithea/public/images/icons/database_lightning.png rename from rhodecode/public/images/icons/database_lightning.png rename to kallithea/public/images/icons/database_lightning.png diff --git a/rhodecode/public/images/icons/database_link.png b/kallithea/public/images/icons/database_link.png rename from rhodecode/public/images/icons/database_link.png rename to kallithea/public/images/icons/database_link.png diff --git a/rhodecode/public/images/icons/database_refresh.png b/kallithea/public/images/icons/database_refresh.png rename from rhodecode/public/images/icons/database_refresh.png rename to kallithea/public/images/icons/database_refresh.png diff --git a/rhodecode/public/images/icons/database_save.png b/kallithea/public/images/icons/database_save.png rename from rhodecode/public/images/icons/database_save.png rename to kallithea/public/images/icons/database_save.png diff --git a/rhodecode/public/images/icons/database_table.png b/kallithea/public/images/icons/database_table.png rename from rhodecode/public/images/icons/database_table.png rename to kallithea/public/images/icons/database_table.png diff --git a/rhodecode/public/images/icons/date.png b/kallithea/public/images/icons/date.png rename from rhodecode/public/images/icons/date.png rename to kallithea/public/images/icons/date.png diff --git a/rhodecode/public/images/icons/date_add.png b/kallithea/public/images/icons/date_add.png rename from rhodecode/public/images/icons/date_add.png rename to kallithea/public/images/icons/date_add.png diff --git a/rhodecode/public/images/icons/date_delete.png b/kallithea/public/images/icons/date_delete.png rename from rhodecode/public/images/icons/date_delete.png rename to kallithea/public/images/icons/date_delete.png diff --git a/rhodecode/public/images/icons/date_edit.png b/kallithea/public/images/icons/date_edit.png rename from rhodecode/public/images/icons/date_edit.png rename to kallithea/public/images/icons/date_edit.png diff --git a/rhodecode/public/images/icons/date_error.png b/kallithea/public/images/icons/date_error.png rename from rhodecode/public/images/icons/date_error.png rename to kallithea/public/images/icons/date_error.png diff --git a/rhodecode/public/images/icons/date_go.png b/kallithea/public/images/icons/date_go.png rename from rhodecode/public/images/icons/date_go.png rename to kallithea/public/images/icons/date_go.png diff --git a/rhodecode/public/images/icons/date_link.png b/kallithea/public/images/icons/date_link.png rename from rhodecode/public/images/icons/date_link.png rename to kallithea/public/images/icons/date_link.png diff --git a/rhodecode/public/images/icons/date_magnify.png b/kallithea/public/images/icons/date_magnify.png rename from rhodecode/public/images/icons/date_magnify.png rename to kallithea/public/images/icons/date_magnify.png diff --git a/rhodecode/public/images/icons/date_next.png b/kallithea/public/images/icons/date_next.png rename from rhodecode/public/images/icons/date_next.png rename to kallithea/public/images/icons/date_next.png diff --git a/rhodecode/public/images/icons/date_previous.png b/kallithea/public/images/icons/date_previous.png rename from rhodecode/public/images/icons/date_previous.png rename to kallithea/public/images/icons/date_previous.png diff --git a/rhodecode/public/images/icons/delete.png b/kallithea/public/images/icons/delete.png rename from rhodecode/public/images/icons/delete.png rename to kallithea/public/images/icons/delete.png diff --git a/rhodecode/public/images/icons/delete_16.png b/kallithea/public/images/icons/delete_16.png rename from rhodecode/public/images/icons/delete_16.png rename to kallithea/public/images/icons/delete_16.png diff --git a/rhodecode/public/images/icons/diagram_16.png b/kallithea/public/images/icons/diagram_16.png rename from rhodecode/public/images/icons/diagram_16.png rename to kallithea/public/images/icons/diagram_16.png diff --git a/rhodecode/public/images/icons/disconnect.png b/kallithea/public/images/icons/disconnect.png rename from rhodecode/public/images/icons/disconnect.png rename to kallithea/public/images/icons/disconnect.png diff --git a/rhodecode/public/images/icons/disk.png b/kallithea/public/images/icons/disk.png rename from rhodecode/public/images/icons/disk.png rename to kallithea/public/images/icons/disk.png diff --git a/rhodecode/public/images/icons/disk_multiple.png b/kallithea/public/images/icons/disk_multiple.png rename from rhodecode/public/images/icons/disk_multiple.png rename to kallithea/public/images/icons/disk_multiple.png diff --git a/rhodecode/public/images/icons/document_16.png b/kallithea/public/images/icons/document_16.png rename from rhodecode/public/images/icons/document_16.png rename to kallithea/public/images/icons/document_16.png diff --git a/rhodecode/public/images/icons/door.png b/kallithea/public/images/icons/door.png rename from rhodecode/public/images/icons/door.png rename to kallithea/public/images/icons/door.png diff --git a/rhodecode/public/images/icons/door_in.png b/kallithea/public/images/icons/door_in.png rename from rhodecode/public/images/icons/door_in.png rename to kallithea/public/images/icons/door_in.png diff --git a/rhodecode/public/images/icons/door_open.png b/kallithea/public/images/icons/door_open.png rename from rhodecode/public/images/icons/door_open.png rename to kallithea/public/images/icons/door_open.png diff --git a/rhodecode/public/images/icons/door_out.png b/kallithea/public/images/icons/door_out.png rename from rhodecode/public/images/icons/door_out.png rename to kallithea/public/images/icons/door_out.png diff --git a/rhodecode/public/images/icons/down_16.png b/kallithea/public/images/icons/down_16.png rename from rhodecode/public/images/icons/down_16.png rename to kallithea/public/images/icons/down_16.png diff --git a/rhodecode/public/images/icons/drink.png b/kallithea/public/images/icons/drink.png rename from rhodecode/public/images/icons/drink.png rename to kallithea/public/images/icons/drink.png diff --git a/rhodecode/public/images/icons/drink_empty.png b/kallithea/public/images/icons/drink_empty.png rename from rhodecode/public/images/icons/drink_empty.png rename to kallithea/public/images/icons/drink_empty.png diff --git a/rhodecode/public/images/icons/drive.png b/kallithea/public/images/icons/drive.png rename from rhodecode/public/images/icons/drive.png rename to kallithea/public/images/icons/drive.png diff --git a/rhodecode/public/images/icons/drive_add.png b/kallithea/public/images/icons/drive_add.png rename from rhodecode/public/images/icons/drive_add.png rename to kallithea/public/images/icons/drive_add.png diff --git a/rhodecode/public/images/icons/drive_burn.png b/kallithea/public/images/icons/drive_burn.png rename from rhodecode/public/images/icons/drive_burn.png rename to kallithea/public/images/icons/drive_burn.png diff --git a/rhodecode/public/images/icons/drive_cd.png b/kallithea/public/images/icons/drive_cd.png rename from rhodecode/public/images/icons/drive_cd.png rename to kallithea/public/images/icons/drive_cd.png diff --git a/rhodecode/public/images/icons/drive_cd_empty.png b/kallithea/public/images/icons/drive_cd_empty.png rename from rhodecode/public/images/icons/drive_cd_empty.png rename to kallithea/public/images/icons/drive_cd_empty.png diff --git a/rhodecode/public/images/icons/drive_delete.png b/kallithea/public/images/icons/drive_delete.png rename from rhodecode/public/images/icons/drive_delete.png rename to kallithea/public/images/icons/drive_delete.png diff --git a/rhodecode/public/images/icons/drive_disk.png b/kallithea/public/images/icons/drive_disk.png rename from rhodecode/public/images/icons/drive_disk.png rename to kallithea/public/images/icons/drive_disk.png diff --git a/rhodecode/public/images/icons/drive_edit.png b/kallithea/public/images/icons/drive_edit.png rename from rhodecode/public/images/icons/drive_edit.png rename to kallithea/public/images/icons/drive_edit.png diff --git a/rhodecode/public/images/icons/drive_error.png b/kallithea/public/images/icons/drive_error.png rename from rhodecode/public/images/icons/drive_error.png rename to kallithea/public/images/icons/drive_error.png diff --git a/rhodecode/public/images/icons/drive_go.png b/kallithea/public/images/icons/drive_go.png rename from rhodecode/public/images/icons/drive_go.png rename to kallithea/public/images/icons/drive_go.png diff --git a/rhodecode/public/images/icons/drive_key.png b/kallithea/public/images/icons/drive_key.png rename from rhodecode/public/images/icons/drive_key.png rename to kallithea/public/images/icons/drive_key.png diff --git a/rhodecode/public/images/icons/drive_link.png b/kallithea/public/images/icons/drive_link.png rename from rhodecode/public/images/icons/drive_link.png rename to kallithea/public/images/icons/drive_link.png diff --git a/rhodecode/public/images/icons/drive_magnify.png b/kallithea/public/images/icons/drive_magnify.png rename from rhodecode/public/images/icons/drive_magnify.png rename to kallithea/public/images/icons/drive_magnify.png diff --git a/rhodecode/public/images/icons/drive_network.png b/kallithea/public/images/icons/drive_network.png rename from rhodecode/public/images/icons/drive_network.png rename to kallithea/public/images/icons/drive_network.png diff --git a/rhodecode/public/images/icons/drive_rename.png b/kallithea/public/images/icons/drive_rename.png rename from rhodecode/public/images/icons/drive_rename.png rename to kallithea/public/images/icons/drive_rename.png diff --git a/rhodecode/public/images/icons/drive_user.png b/kallithea/public/images/icons/drive_user.png rename from rhodecode/public/images/icons/drive_user.png rename to kallithea/public/images/icons/drive_user.png diff --git a/rhodecode/public/images/icons/drive_web.png b/kallithea/public/images/icons/drive_web.png rename from rhodecode/public/images/icons/drive_web.png rename to kallithea/public/images/icons/drive_web.png diff --git a/rhodecode/public/images/icons/dvd.png b/kallithea/public/images/icons/dvd.png rename from rhodecode/public/images/icons/dvd.png rename to kallithea/public/images/icons/dvd.png diff --git a/rhodecode/public/images/icons/dvd_add.png b/kallithea/public/images/icons/dvd_add.png rename from rhodecode/public/images/icons/dvd_add.png rename to kallithea/public/images/icons/dvd_add.png diff --git a/rhodecode/public/images/icons/dvd_delete.png b/kallithea/public/images/icons/dvd_delete.png rename from rhodecode/public/images/icons/dvd_delete.png rename to kallithea/public/images/icons/dvd_delete.png diff --git a/rhodecode/public/images/icons/dvd_edit.png b/kallithea/public/images/icons/dvd_edit.png rename from rhodecode/public/images/icons/dvd_edit.png rename to kallithea/public/images/icons/dvd_edit.png diff --git a/rhodecode/public/images/icons/dvd_error.png b/kallithea/public/images/icons/dvd_error.png rename from rhodecode/public/images/icons/dvd_error.png rename to kallithea/public/images/icons/dvd_error.png diff --git a/rhodecode/public/images/icons/dvd_go.png b/kallithea/public/images/icons/dvd_go.png rename from rhodecode/public/images/icons/dvd_go.png rename to kallithea/public/images/icons/dvd_go.png diff --git a/rhodecode/public/images/icons/dvd_key.png b/kallithea/public/images/icons/dvd_key.png rename from rhodecode/public/images/icons/dvd_key.png rename to kallithea/public/images/icons/dvd_key.png diff --git a/rhodecode/public/images/icons/dvd_link.png b/kallithea/public/images/icons/dvd_link.png rename from rhodecode/public/images/icons/dvd_link.png rename to kallithea/public/images/icons/dvd_link.png diff --git a/rhodecode/public/images/icons/email.png b/kallithea/public/images/icons/email.png rename from rhodecode/public/images/icons/email.png rename to kallithea/public/images/icons/email.png diff --git a/rhodecode/public/images/icons/email_add.png b/kallithea/public/images/icons/email_add.png rename from rhodecode/public/images/icons/email_add.png rename to kallithea/public/images/icons/email_add.png diff --git a/rhodecode/public/images/icons/email_attach.png b/kallithea/public/images/icons/email_attach.png rename from rhodecode/public/images/icons/email_attach.png rename to kallithea/public/images/icons/email_attach.png diff --git a/rhodecode/public/images/icons/email_delete.png b/kallithea/public/images/icons/email_delete.png rename from rhodecode/public/images/icons/email_delete.png rename to kallithea/public/images/icons/email_delete.png diff --git a/rhodecode/public/images/icons/email_edit.png b/kallithea/public/images/icons/email_edit.png rename from rhodecode/public/images/icons/email_edit.png rename to kallithea/public/images/icons/email_edit.png diff --git a/rhodecode/public/images/icons/email_error.png b/kallithea/public/images/icons/email_error.png rename from rhodecode/public/images/icons/email_error.png rename to kallithea/public/images/icons/email_error.png diff --git a/rhodecode/public/images/icons/email_go.png b/kallithea/public/images/icons/email_go.png rename from rhodecode/public/images/icons/email_go.png rename to kallithea/public/images/icons/email_go.png diff --git a/rhodecode/public/images/icons/email_link.png b/kallithea/public/images/icons/email_link.png rename from rhodecode/public/images/icons/email_link.png rename to kallithea/public/images/icons/email_link.png diff --git a/rhodecode/public/images/icons/email_open.png b/kallithea/public/images/icons/email_open.png rename from rhodecode/public/images/icons/email_open.png rename to kallithea/public/images/icons/email_open.png diff --git a/rhodecode/public/images/icons/email_open_image.png b/kallithea/public/images/icons/email_open_image.png rename from rhodecode/public/images/icons/email_open_image.png rename to kallithea/public/images/icons/email_open_image.png diff --git a/rhodecode/public/images/icons/emoticon_evilgrin.png b/kallithea/public/images/icons/emoticon_evilgrin.png rename from rhodecode/public/images/icons/emoticon_evilgrin.png rename to kallithea/public/images/icons/emoticon_evilgrin.png diff --git a/rhodecode/public/images/icons/emoticon_grin.png b/kallithea/public/images/icons/emoticon_grin.png rename from rhodecode/public/images/icons/emoticon_grin.png rename to kallithea/public/images/icons/emoticon_grin.png diff --git a/rhodecode/public/images/icons/emoticon_happy.png b/kallithea/public/images/icons/emoticon_happy.png rename from rhodecode/public/images/icons/emoticon_happy.png rename to kallithea/public/images/icons/emoticon_happy.png diff --git a/rhodecode/public/images/icons/emoticon_smile.png b/kallithea/public/images/icons/emoticon_smile.png rename from rhodecode/public/images/icons/emoticon_smile.png rename to kallithea/public/images/icons/emoticon_smile.png diff --git a/rhodecode/public/images/icons/emoticon_surprised.png b/kallithea/public/images/icons/emoticon_surprised.png rename from rhodecode/public/images/icons/emoticon_surprised.png rename to kallithea/public/images/icons/emoticon_surprised.png diff --git a/rhodecode/public/images/icons/emoticon_tongue.png b/kallithea/public/images/icons/emoticon_tongue.png rename from rhodecode/public/images/icons/emoticon_tongue.png rename to kallithea/public/images/icons/emoticon_tongue.png diff --git a/rhodecode/public/images/icons/emoticon_unhappy.png b/kallithea/public/images/icons/emoticon_unhappy.png rename from rhodecode/public/images/icons/emoticon_unhappy.png rename to kallithea/public/images/icons/emoticon_unhappy.png diff --git a/rhodecode/public/images/icons/emoticon_waii.png b/kallithea/public/images/icons/emoticon_waii.png rename from rhodecode/public/images/icons/emoticon_waii.png rename to kallithea/public/images/icons/emoticon_waii.png diff --git a/rhodecode/public/images/icons/emoticon_wink.png b/kallithea/public/images/icons/emoticon_wink.png rename from rhodecode/public/images/icons/emoticon_wink.png rename to kallithea/public/images/icons/emoticon_wink.png diff --git a/rhodecode/public/images/icons/error.png b/kallithea/public/images/icons/error.png rename from rhodecode/public/images/icons/error.png rename to kallithea/public/images/icons/error.png diff --git a/rhodecode/public/images/icons/error_add.png b/kallithea/public/images/icons/error_add.png rename from rhodecode/public/images/icons/error_add.png rename to kallithea/public/images/icons/error_add.png diff --git a/rhodecode/public/images/icons/error_delete.png b/kallithea/public/images/icons/error_delete.png rename from rhodecode/public/images/icons/error_delete.png rename to kallithea/public/images/icons/error_delete.png diff --git a/rhodecode/public/images/icons/error_go.png b/kallithea/public/images/icons/error_go.png rename from rhodecode/public/images/icons/error_go.png rename to kallithea/public/images/icons/error_go.png diff --git a/rhodecode/public/images/icons/error_msg.png b/kallithea/public/images/icons/error_msg.png rename from rhodecode/public/images/icons/error_msg.png rename to kallithea/public/images/icons/error_msg.png diff --git a/rhodecode/public/images/icons/exclamation.png b/kallithea/public/images/icons/exclamation.png rename from rhodecode/public/images/icons/exclamation.png rename to kallithea/public/images/icons/exclamation.png diff --git a/rhodecode/public/images/icons/eye.png b/kallithea/public/images/icons/eye.png rename from rhodecode/public/images/icons/eye.png rename to kallithea/public/images/icons/eye.png diff --git a/rhodecode/public/images/icons/feed.png b/kallithea/public/images/icons/feed.png rename from rhodecode/public/images/icons/feed.png rename to kallithea/public/images/icons/feed.png diff --git a/rhodecode/public/images/icons/feed_add.png b/kallithea/public/images/icons/feed_add.png rename from rhodecode/public/images/icons/feed_add.png rename to kallithea/public/images/icons/feed_add.png diff --git a/rhodecode/public/images/icons/feed_delete.png b/kallithea/public/images/icons/feed_delete.png rename from rhodecode/public/images/icons/feed_delete.png rename to kallithea/public/images/icons/feed_delete.png diff --git a/rhodecode/public/images/icons/feed_disk.png b/kallithea/public/images/icons/feed_disk.png rename from rhodecode/public/images/icons/feed_disk.png rename to kallithea/public/images/icons/feed_disk.png diff --git a/rhodecode/public/images/icons/feed_edit.png b/kallithea/public/images/icons/feed_edit.png rename from rhodecode/public/images/icons/feed_edit.png rename to kallithea/public/images/icons/feed_edit.png diff --git a/rhodecode/public/images/icons/feed_error.png b/kallithea/public/images/icons/feed_error.png rename from rhodecode/public/images/icons/feed_error.png rename to kallithea/public/images/icons/feed_error.png diff --git a/rhodecode/public/images/icons/feed_go.png b/kallithea/public/images/icons/feed_go.png rename from rhodecode/public/images/icons/feed_go.png rename to kallithea/public/images/icons/feed_go.png diff --git a/rhodecode/public/images/icons/feed_key.png b/kallithea/public/images/icons/feed_key.png rename from rhodecode/public/images/icons/feed_key.png rename to kallithea/public/images/icons/feed_key.png diff --git a/rhodecode/public/images/icons/feed_link.png b/kallithea/public/images/icons/feed_link.png rename from rhodecode/public/images/icons/feed_link.png rename to kallithea/public/images/icons/feed_link.png diff --git a/rhodecode/public/images/icons/feed_magnify.png b/kallithea/public/images/icons/feed_magnify.png rename from rhodecode/public/images/icons/feed_magnify.png rename to kallithea/public/images/icons/feed_magnify.png diff --git a/rhodecode/public/images/icons/female.png b/kallithea/public/images/icons/female.png rename from rhodecode/public/images/icons/female.png rename to kallithea/public/images/icons/female.png diff --git a/rhodecode/public/images/icons/file.png b/kallithea/public/images/icons/file.png rename from rhodecode/public/images/icons/file.png rename to kallithea/public/images/icons/file.png diff --git a/rhodecode/public/images/icons/film.png b/kallithea/public/images/icons/film.png rename from rhodecode/public/images/icons/film.png rename to kallithea/public/images/icons/film.png diff --git a/rhodecode/public/images/icons/film_add.png b/kallithea/public/images/icons/film_add.png rename from rhodecode/public/images/icons/film_add.png rename to kallithea/public/images/icons/film_add.png diff --git a/rhodecode/public/images/icons/film_delete.png b/kallithea/public/images/icons/film_delete.png rename from rhodecode/public/images/icons/film_delete.png rename to kallithea/public/images/icons/film_delete.png diff --git a/rhodecode/public/images/icons/film_edit.png b/kallithea/public/images/icons/film_edit.png rename from rhodecode/public/images/icons/film_edit.png rename to kallithea/public/images/icons/film_edit.png diff --git a/rhodecode/public/images/icons/film_error.png b/kallithea/public/images/icons/film_error.png rename from rhodecode/public/images/icons/film_error.png rename to kallithea/public/images/icons/film_error.png diff --git a/rhodecode/public/images/icons/film_go.png b/kallithea/public/images/icons/film_go.png rename from rhodecode/public/images/icons/film_go.png rename to kallithea/public/images/icons/film_go.png diff --git a/rhodecode/public/images/icons/film_key.png b/kallithea/public/images/icons/film_key.png rename from rhodecode/public/images/icons/film_key.png rename to kallithea/public/images/icons/film_key.png diff --git a/rhodecode/public/images/icons/film_link.png b/kallithea/public/images/icons/film_link.png rename from rhodecode/public/images/icons/film_link.png rename to kallithea/public/images/icons/film_link.png diff --git a/rhodecode/public/images/icons/film_save.png b/kallithea/public/images/icons/film_save.png rename from rhodecode/public/images/icons/film_save.png rename to kallithea/public/images/icons/film_save.png diff --git a/rhodecode/public/images/icons/find.png b/kallithea/public/images/icons/find.png rename from rhodecode/public/images/icons/find.png rename to kallithea/public/images/icons/find.png diff --git a/rhodecode/public/images/icons/flag_16.png b/kallithea/public/images/icons/flag_16.png rename from rhodecode/public/images/icons/flag_16.png rename to kallithea/public/images/icons/flag_16.png diff --git a/rhodecode/public/images/icons/flag_blue.png b/kallithea/public/images/icons/flag_blue.png rename from rhodecode/public/images/icons/flag_blue.png rename to kallithea/public/images/icons/flag_blue.png diff --git a/rhodecode/public/images/icons/flag_green.png b/kallithea/public/images/icons/flag_green.png rename from rhodecode/public/images/icons/flag_green.png rename to kallithea/public/images/icons/flag_green.png diff --git a/rhodecode/public/images/icons/flag_orange.png b/kallithea/public/images/icons/flag_orange.png rename from rhodecode/public/images/icons/flag_orange.png rename to kallithea/public/images/icons/flag_orange.png diff --git a/rhodecode/public/images/icons/flag_pink.png b/kallithea/public/images/icons/flag_pink.png rename from rhodecode/public/images/icons/flag_pink.png rename to kallithea/public/images/icons/flag_pink.png diff --git a/rhodecode/public/images/icons/flag_purple.png b/kallithea/public/images/icons/flag_purple.png rename from rhodecode/public/images/icons/flag_purple.png rename to kallithea/public/images/icons/flag_purple.png diff --git a/rhodecode/public/images/icons/flag_red.png b/kallithea/public/images/icons/flag_red.png rename from rhodecode/public/images/icons/flag_red.png rename to kallithea/public/images/icons/flag_red.png diff --git a/rhodecode/public/images/icons/flag_status_approved.png b/kallithea/public/images/icons/flag_status_approved.png rename from rhodecode/public/images/icons/flag_status_approved.png rename to kallithea/public/images/icons/flag_status_approved.png diff --git a/rhodecode/public/images/icons/flag_status_not_reviewed.png b/kallithea/public/images/icons/flag_status_not_reviewed.png rename from rhodecode/public/images/icons/flag_status_not_reviewed.png rename to kallithea/public/images/icons/flag_status_not_reviewed.png diff --git a/rhodecode/public/images/icons/flag_status_rejected.png b/kallithea/public/images/icons/flag_status_rejected.png rename from rhodecode/public/images/icons/flag_status_rejected.png rename to kallithea/public/images/icons/flag_status_rejected.png diff --git a/rhodecode/public/images/icons/flag_status_under_review.png b/kallithea/public/images/icons/flag_status_under_review.png rename from rhodecode/public/images/icons/flag_status_under_review.png rename to kallithea/public/images/icons/flag_status_under_review.png diff --git a/rhodecode/public/images/icons/flag_yellow.png b/kallithea/public/images/icons/flag_yellow.png rename from rhodecode/public/images/icons/flag_yellow.png rename to kallithea/public/images/icons/flag_yellow.png diff --git a/rhodecode/public/images/icons/folder.png b/kallithea/public/images/icons/folder.png rename from rhodecode/public/images/icons/folder.png rename to kallithea/public/images/icons/folder.png diff --git a/rhodecode/public/images/icons/folder_16.png b/kallithea/public/images/icons/folder_16.png rename from rhodecode/public/images/icons/folder_16.png rename to kallithea/public/images/icons/folder_16.png diff --git a/rhodecode/public/images/icons/folder_add.png b/kallithea/public/images/icons/folder_add.png rename from rhodecode/public/images/icons/folder_add.png rename to kallithea/public/images/icons/folder_add.png diff --git a/rhodecode/public/images/icons/folder_bell.png b/kallithea/public/images/icons/folder_bell.png rename from rhodecode/public/images/icons/folder_bell.png rename to kallithea/public/images/icons/folder_bell.png diff --git a/rhodecode/public/images/icons/folder_brick.png b/kallithea/public/images/icons/folder_brick.png rename from rhodecode/public/images/icons/folder_brick.png rename to kallithea/public/images/icons/folder_brick.png diff --git a/rhodecode/public/images/icons/folder_bug.png b/kallithea/public/images/icons/folder_bug.png rename from rhodecode/public/images/icons/folder_bug.png rename to kallithea/public/images/icons/folder_bug.png diff --git a/rhodecode/public/images/icons/folder_camera.png b/kallithea/public/images/icons/folder_camera.png rename from rhodecode/public/images/icons/folder_camera.png rename to kallithea/public/images/icons/folder_camera.png diff --git a/rhodecode/public/images/icons/folder_database.png b/kallithea/public/images/icons/folder_database.png rename from rhodecode/public/images/icons/folder_database.png rename to kallithea/public/images/icons/folder_database.png diff --git a/rhodecode/public/images/icons/folder_delete.png b/kallithea/public/images/icons/folder_delete.png rename from rhodecode/public/images/icons/folder_delete.png rename to kallithea/public/images/icons/folder_delete.png diff --git a/rhodecode/public/images/icons/folder_edit.png b/kallithea/public/images/icons/folder_edit.png rename from rhodecode/public/images/icons/folder_edit.png rename to kallithea/public/images/icons/folder_edit.png diff --git a/rhodecode/public/images/icons/folder_error.png b/kallithea/public/images/icons/folder_error.png rename from rhodecode/public/images/icons/folder_error.png rename to kallithea/public/images/icons/folder_error.png diff --git a/rhodecode/public/images/icons/folder_explore.png b/kallithea/public/images/icons/folder_explore.png rename from rhodecode/public/images/icons/folder_explore.png rename to kallithea/public/images/icons/folder_explore.png diff --git a/rhodecode/public/images/icons/folder_feed.png b/kallithea/public/images/icons/folder_feed.png rename from rhodecode/public/images/icons/folder_feed.png rename to kallithea/public/images/icons/folder_feed.png diff --git a/rhodecode/public/images/icons/folder_find.png b/kallithea/public/images/icons/folder_find.png rename from rhodecode/public/images/icons/folder_find.png rename to kallithea/public/images/icons/folder_find.png diff --git a/rhodecode/public/images/icons/folder_go.png b/kallithea/public/images/icons/folder_go.png rename from rhodecode/public/images/icons/folder_go.png rename to kallithea/public/images/icons/folder_go.png diff --git a/rhodecode/public/images/icons/folder_heart.png b/kallithea/public/images/icons/folder_heart.png rename from rhodecode/public/images/icons/folder_heart.png rename to kallithea/public/images/icons/folder_heart.png diff --git a/rhodecode/public/images/icons/folder_image.png b/kallithea/public/images/icons/folder_image.png rename from rhodecode/public/images/icons/folder_image.png rename to kallithea/public/images/icons/folder_image.png diff --git a/rhodecode/public/images/icons/folder_key.png b/kallithea/public/images/icons/folder_key.png rename from rhodecode/public/images/icons/folder_key.png rename to kallithea/public/images/icons/folder_key.png diff --git a/rhodecode/public/images/icons/folder_lightbulb.png b/kallithea/public/images/icons/folder_lightbulb.png rename from rhodecode/public/images/icons/folder_lightbulb.png rename to kallithea/public/images/icons/folder_lightbulb.png diff --git a/rhodecode/public/images/icons/folder_link.png b/kallithea/public/images/icons/folder_link.png rename from rhodecode/public/images/icons/folder_link.png rename to kallithea/public/images/icons/folder_link.png diff --git a/rhodecode/public/images/icons/folder_magnify.png b/kallithea/public/images/icons/folder_magnify.png rename from rhodecode/public/images/icons/folder_magnify.png rename to kallithea/public/images/icons/folder_magnify.png diff --git a/rhodecode/public/images/icons/folder_page.png b/kallithea/public/images/icons/folder_page.png rename from rhodecode/public/images/icons/folder_page.png rename to kallithea/public/images/icons/folder_page.png diff --git a/rhodecode/public/images/icons/folder_page_white.png b/kallithea/public/images/icons/folder_page_white.png rename from rhodecode/public/images/icons/folder_page_white.png rename to kallithea/public/images/icons/folder_page_white.png diff --git a/rhodecode/public/images/icons/folder_palette.png b/kallithea/public/images/icons/folder_palette.png rename from rhodecode/public/images/icons/folder_palette.png rename to kallithea/public/images/icons/folder_palette.png diff --git a/rhodecode/public/images/icons/folder_picture.png b/kallithea/public/images/icons/folder_picture.png rename from rhodecode/public/images/icons/folder_picture.png rename to kallithea/public/images/icons/folder_picture.png diff --git a/rhodecode/public/images/icons/folder_star.png b/kallithea/public/images/icons/folder_star.png rename from rhodecode/public/images/icons/folder_star.png rename to kallithea/public/images/icons/folder_star.png diff --git a/rhodecode/public/images/icons/folder_table.png b/kallithea/public/images/icons/folder_table.png rename from rhodecode/public/images/icons/folder_table.png rename to kallithea/public/images/icons/folder_table.png diff --git a/rhodecode/public/images/icons/folder_user.png b/kallithea/public/images/icons/folder_user.png rename from rhodecode/public/images/icons/folder_user.png rename to kallithea/public/images/icons/folder_user.png diff --git a/rhodecode/public/images/icons/folder_wrench.png b/kallithea/public/images/icons/folder_wrench.png rename from rhodecode/public/images/icons/folder_wrench.png rename to kallithea/public/images/icons/folder_wrench.png diff --git a/rhodecode/public/images/icons/font.png b/kallithea/public/images/icons/font.png rename from rhodecode/public/images/icons/font.png rename to kallithea/public/images/icons/font.png diff --git a/rhodecode/public/images/icons/font_add.png b/kallithea/public/images/icons/font_add.png rename from rhodecode/public/images/icons/font_add.png rename to kallithea/public/images/icons/font_add.png diff --git a/rhodecode/public/images/icons/font_delete.png b/kallithea/public/images/icons/font_delete.png rename from rhodecode/public/images/icons/font_delete.png rename to kallithea/public/images/icons/font_delete.png diff --git a/rhodecode/public/images/icons/font_go.png b/kallithea/public/images/icons/font_go.png rename from rhodecode/public/images/icons/font_go.png rename to kallithea/public/images/icons/font_go.png diff --git a/rhodecode/public/images/icons/gear_16.png b/kallithea/public/images/icons/gear_16.png rename from rhodecode/public/images/icons/gear_16.png rename to kallithea/public/images/icons/gear_16.png diff --git a/rhodecode/public/images/icons/giticon.png b/kallithea/public/images/icons/giticon.png rename from rhodecode/public/images/icons/giticon.png rename to kallithea/public/images/icons/giticon.png diff --git a/rhodecode/public/images/icons/globe_16.png b/kallithea/public/images/icons/globe_16.png rename from rhodecode/public/images/icons/globe_16.png rename to kallithea/public/images/icons/globe_16.png diff --git a/rhodecode/public/images/icons/group.png b/kallithea/public/images/icons/group.png rename from rhodecode/public/images/icons/group.png rename to kallithea/public/images/icons/group.png diff --git a/rhodecode/public/images/icons/group_add.png b/kallithea/public/images/icons/group_add.png rename from rhodecode/public/images/icons/group_add.png rename to kallithea/public/images/icons/group_add.png diff --git a/rhodecode/public/images/icons/group_delete.png b/kallithea/public/images/icons/group_delete.png rename from rhodecode/public/images/icons/group_delete.png rename to kallithea/public/images/icons/group_delete.png diff --git a/rhodecode/public/images/icons/group_edit.png b/kallithea/public/images/icons/group_edit.png rename from rhodecode/public/images/icons/group_edit.png rename to kallithea/public/images/icons/group_edit.png diff --git a/rhodecode/public/images/icons/group_error.png b/kallithea/public/images/icons/group_error.png rename from rhodecode/public/images/icons/group_error.png rename to kallithea/public/images/icons/group_error.png diff --git a/rhodecode/public/images/icons/group_gear.png b/kallithea/public/images/icons/group_gear.png rename from rhodecode/public/images/icons/group_gear.png rename to kallithea/public/images/icons/group_gear.png diff --git a/rhodecode/public/images/icons/group_go.png b/kallithea/public/images/icons/group_go.png rename from rhodecode/public/images/icons/group_go.png rename to kallithea/public/images/icons/group_go.png diff --git a/rhodecode/public/images/icons/group_key.png b/kallithea/public/images/icons/group_key.png rename from rhodecode/public/images/icons/group_key.png rename to kallithea/public/images/icons/group_key.png diff --git a/rhodecode/public/images/icons/group_link.png b/kallithea/public/images/icons/group_link.png rename from rhodecode/public/images/icons/group_link.png rename to kallithea/public/images/icons/group_link.png diff --git a/rhodecode/public/images/icons/heart.png b/kallithea/public/images/icons/heart.png rename from rhodecode/public/images/icons/heart.png rename to kallithea/public/images/icons/heart.png diff --git a/rhodecode/public/images/icons/heart_16.png b/kallithea/public/images/icons/heart_16.png rename from rhodecode/public/images/icons/heart_16.png rename to kallithea/public/images/icons/heart_16.png diff --git a/rhodecode/public/images/icons/heart_add.png b/kallithea/public/images/icons/heart_add.png rename from rhodecode/public/images/icons/heart_add.png rename to kallithea/public/images/icons/heart_add.png diff --git a/rhodecode/public/images/icons/heart_delete.png b/kallithea/public/images/icons/heart_delete.png rename from rhodecode/public/images/icons/heart_delete.png rename to kallithea/public/images/icons/heart_delete.png diff --git a/rhodecode/public/images/icons/help.png b/kallithea/public/images/icons/help.png rename from rhodecode/public/images/icons/help.png rename to kallithea/public/images/icons/help.png diff --git a/rhodecode/public/images/icons/help_16.png b/kallithea/public/images/icons/help_16.png rename from rhodecode/public/images/icons/help_16.png rename to kallithea/public/images/icons/help_16.png diff --git a/rhodecode/public/images/icons/hgicon.png b/kallithea/public/images/icons/hgicon.png rename from rhodecode/public/images/icons/hgicon.png rename to kallithea/public/images/icons/hgicon.png diff --git a/rhodecode/public/images/icons/home_16.png b/kallithea/public/images/icons/home_16.png rename from rhodecode/public/images/icons/home_16.png rename to kallithea/public/images/icons/home_16.png diff --git a/rhodecode/public/images/icons/hourglass.png b/kallithea/public/images/icons/hourglass.png rename from rhodecode/public/images/icons/hourglass.png rename to kallithea/public/images/icons/hourglass.png diff --git a/rhodecode/public/images/icons/hourglass_add.png b/kallithea/public/images/icons/hourglass_add.png rename from rhodecode/public/images/icons/hourglass_add.png rename to kallithea/public/images/icons/hourglass_add.png diff --git a/rhodecode/public/images/icons/hourglass_delete.png b/kallithea/public/images/icons/hourglass_delete.png rename from rhodecode/public/images/icons/hourglass_delete.png rename to kallithea/public/images/icons/hourglass_delete.png diff --git a/rhodecode/public/images/icons/hourglass_go.png b/kallithea/public/images/icons/hourglass_go.png rename from rhodecode/public/images/icons/hourglass_go.png rename to kallithea/public/images/icons/hourglass_go.png diff --git a/rhodecode/public/images/icons/hourglass_link.png b/kallithea/public/images/icons/hourglass_link.png rename from rhodecode/public/images/icons/hourglass_link.png rename to kallithea/public/images/icons/hourglass_link.png diff --git a/rhodecode/public/images/icons/house.png b/kallithea/public/images/icons/house.png rename from rhodecode/public/images/icons/house.png rename to kallithea/public/images/icons/house.png diff --git a/rhodecode/public/images/icons/house_go.png b/kallithea/public/images/icons/house_go.png rename from rhodecode/public/images/icons/house_go.png rename to kallithea/public/images/icons/house_go.png diff --git a/rhodecode/public/images/icons/house_link.png b/kallithea/public/images/icons/house_link.png rename from rhodecode/public/images/icons/house_link.png rename to kallithea/public/images/icons/house_link.png diff --git a/rhodecode/public/images/icons/html.png b/kallithea/public/images/icons/html.png rename from rhodecode/public/images/icons/html.png rename to kallithea/public/images/icons/html.png diff --git a/rhodecode/public/images/icons/html_add.png b/kallithea/public/images/icons/html_add.png rename from rhodecode/public/images/icons/html_add.png rename to kallithea/public/images/icons/html_add.png diff --git a/rhodecode/public/images/icons/html_delete.png b/kallithea/public/images/icons/html_delete.png rename from rhodecode/public/images/icons/html_delete.png rename to kallithea/public/images/icons/html_delete.png diff --git a/rhodecode/public/images/icons/html_go.png b/kallithea/public/images/icons/html_go.png rename from rhodecode/public/images/icons/html_go.png rename to kallithea/public/images/icons/html_go.png diff --git a/rhodecode/public/images/icons/html_valid.png b/kallithea/public/images/icons/html_valid.png rename from rhodecode/public/images/icons/html_valid.png rename to kallithea/public/images/icons/html_valid.png diff --git a/rhodecode/public/images/icons/image.png b/kallithea/public/images/icons/image.png rename from rhodecode/public/images/icons/image.png rename to kallithea/public/images/icons/image.png diff --git a/rhodecode/public/images/icons/image_add.png b/kallithea/public/images/icons/image_add.png rename from rhodecode/public/images/icons/image_add.png rename to kallithea/public/images/icons/image_add.png diff --git a/rhodecode/public/images/icons/image_delete.png b/kallithea/public/images/icons/image_delete.png rename from rhodecode/public/images/icons/image_delete.png rename to kallithea/public/images/icons/image_delete.png diff --git a/rhodecode/public/images/icons/image_edit.png b/kallithea/public/images/icons/image_edit.png rename from rhodecode/public/images/icons/image_edit.png rename to kallithea/public/images/icons/image_edit.png diff --git a/rhodecode/public/images/icons/image_link.png b/kallithea/public/images/icons/image_link.png rename from rhodecode/public/images/icons/image_link.png rename to kallithea/public/images/icons/image_link.png diff --git a/rhodecode/public/images/icons/images.png b/kallithea/public/images/icons/images.png rename from rhodecode/public/images/icons/images.png rename to kallithea/public/images/icons/images.png diff --git a/rhodecode/public/images/icons/info_16.png b/kallithea/public/images/icons/info_16.png rename from rhodecode/public/images/icons/info_16.png rename to kallithea/public/images/icons/info_16.png diff --git a/rhodecode/public/images/icons/information.png b/kallithea/public/images/icons/information.png rename from rhodecode/public/images/icons/information.png rename to kallithea/public/images/icons/information.png diff --git a/rhodecode/public/images/icons/ipod.png b/kallithea/public/images/icons/ipod.png rename from rhodecode/public/images/icons/ipod.png rename to kallithea/public/images/icons/ipod.png diff --git a/rhodecode/public/images/icons/ipod_cast.png b/kallithea/public/images/icons/ipod_cast.png rename from rhodecode/public/images/icons/ipod_cast.png rename to kallithea/public/images/icons/ipod_cast.png diff --git a/rhodecode/public/images/icons/ipod_cast_add.png b/kallithea/public/images/icons/ipod_cast_add.png rename from rhodecode/public/images/icons/ipod_cast_add.png rename to kallithea/public/images/icons/ipod_cast_add.png diff --git a/rhodecode/public/images/icons/ipod_cast_delete.png b/kallithea/public/images/icons/ipod_cast_delete.png rename from rhodecode/public/images/icons/ipod_cast_delete.png rename to kallithea/public/images/icons/ipod_cast_delete.png diff --git a/rhodecode/public/images/icons/ipod_sound.png b/kallithea/public/images/icons/ipod_sound.png rename from rhodecode/public/images/icons/ipod_sound.png rename to kallithea/public/images/icons/ipod_sound.png diff --git a/rhodecode/public/images/icons/joystick.png b/kallithea/public/images/icons/joystick.png rename from rhodecode/public/images/icons/joystick.png rename to kallithea/public/images/icons/joystick.png diff --git a/rhodecode/public/images/icons/joystick_add.png b/kallithea/public/images/icons/joystick_add.png rename from rhodecode/public/images/icons/joystick_add.png rename to kallithea/public/images/icons/joystick_add.png diff --git a/rhodecode/public/images/icons/joystick_delete.png b/kallithea/public/images/icons/joystick_delete.png rename from rhodecode/public/images/icons/joystick_delete.png rename to kallithea/public/images/icons/joystick_delete.png diff --git a/rhodecode/public/images/icons/joystick_error.png b/kallithea/public/images/icons/joystick_error.png rename from rhodecode/public/images/icons/joystick_error.png rename to kallithea/public/images/icons/joystick_error.png diff --git a/rhodecode/public/images/icons/key.png b/kallithea/public/images/icons/key.png rename from rhodecode/public/images/icons/key.png rename to kallithea/public/images/icons/key.png diff --git a/rhodecode/public/images/icons/key_16.png b/kallithea/public/images/icons/key_16.png rename from rhodecode/public/images/icons/key_16.png rename to kallithea/public/images/icons/key_16.png diff --git a/rhodecode/public/images/icons/key_add.png b/kallithea/public/images/icons/key_add.png rename from rhodecode/public/images/icons/key_add.png rename to kallithea/public/images/icons/key_add.png diff --git a/rhodecode/public/images/icons/key_delete.png b/kallithea/public/images/icons/key_delete.png rename from rhodecode/public/images/icons/key_delete.png rename to kallithea/public/images/icons/key_delete.png diff --git a/rhodecode/public/images/icons/key_go.png b/kallithea/public/images/icons/key_go.png rename from rhodecode/public/images/icons/key_go.png rename to kallithea/public/images/icons/key_go.png diff --git a/rhodecode/public/images/icons/keyboard.png b/kallithea/public/images/icons/keyboard.png rename from rhodecode/public/images/icons/keyboard.png rename to kallithea/public/images/icons/keyboard.png diff --git a/rhodecode/public/images/icons/keyboard_add.png b/kallithea/public/images/icons/keyboard_add.png rename from rhodecode/public/images/icons/keyboard_add.png rename to kallithea/public/images/icons/keyboard_add.png diff --git a/rhodecode/public/images/icons/keyboard_delete.png b/kallithea/public/images/icons/keyboard_delete.png rename from rhodecode/public/images/icons/keyboard_delete.png rename to kallithea/public/images/icons/keyboard_delete.png diff --git a/rhodecode/public/images/icons/keyboard_magnify.png b/kallithea/public/images/icons/keyboard_magnify.png rename from rhodecode/public/images/icons/keyboard_magnify.png rename to kallithea/public/images/icons/keyboard_magnify.png diff --git a/rhodecode/public/images/icons/label_16.png b/kallithea/public/images/icons/label_16.png rename from rhodecode/public/images/icons/label_16.png rename to kallithea/public/images/icons/label_16.png diff --git a/rhodecode/public/images/icons/layers.png b/kallithea/public/images/icons/layers.png rename from rhodecode/public/images/icons/layers.png rename to kallithea/public/images/icons/layers.png diff --git a/rhodecode/public/images/icons/layout.png b/kallithea/public/images/icons/layout.png rename from rhodecode/public/images/icons/layout.png rename to kallithea/public/images/icons/layout.png diff --git a/rhodecode/public/images/icons/layout_add.png b/kallithea/public/images/icons/layout_add.png rename from rhodecode/public/images/icons/layout_add.png rename to kallithea/public/images/icons/layout_add.png diff --git a/rhodecode/public/images/icons/layout_content.png b/kallithea/public/images/icons/layout_content.png rename from rhodecode/public/images/icons/layout_content.png rename to kallithea/public/images/icons/layout_content.png diff --git a/rhodecode/public/images/icons/layout_delete.png b/kallithea/public/images/icons/layout_delete.png rename from rhodecode/public/images/icons/layout_delete.png rename to kallithea/public/images/icons/layout_delete.png diff --git a/rhodecode/public/images/icons/layout_edit.png b/kallithea/public/images/icons/layout_edit.png rename from rhodecode/public/images/icons/layout_edit.png rename to kallithea/public/images/icons/layout_edit.png diff --git a/rhodecode/public/images/icons/layout_error.png b/kallithea/public/images/icons/layout_error.png rename from rhodecode/public/images/icons/layout_error.png rename to kallithea/public/images/icons/layout_error.png diff --git a/rhodecode/public/images/icons/layout_header.png b/kallithea/public/images/icons/layout_header.png rename from rhodecode/public/images/icons/layout_header.png rename to kallithea/public/images/icons/layout_header.png diff --git a/rhodecode/public/images/icons/layout_link.png b/kallithea/public/images/icons/layout_link.png rename from rhodecode/public/images/icons/layout_link.png rename to kallithea/public/images/icons/layout_link.png diff --git a/rhodecode/public/images/icons/layout_sidebar.png b/kallithea/public/images/icons/layout_sidebar.png rename from rhodecode/public/images/icons/layout_sidebar.png rename to kallithea/public/images/icons/layout_sidebar.png diff --git a/rhodecode/public/images/icons/left_16.png b/kallithea/public/images/icons/left_16.png rename from rhodecode/public/images/icons/left_16.png rename to kallithea/public/images/icons/left_16.png diff --git a/rhodecode/public/images/icons/letter_16.png b/kallithea/public/images/icons/letter_16.png rename from rhodecode/public/images/icons/letter_16.png rename to kallithea/public/images/icons/letter_16.png diff --git a/rhodecode/public/images/icons/lightbulb.png b/kallithea/public/images/icons/lightbulb.png rename from rhodecode/public/images/icons/lightbulb.png rename to kallithea/public/images/icons/lightbulb.png diff --git a/rhodecode/public/images/icons/lightbulb_add.png b/kallithea/public/images/icons/lightbulb_add.png rename from rhodecode/public/images/icons/lightbulb_add.png rename to kallithea/public/images/icons/lightbulb_add.png diff --git a/rhodecode/public/images/icons/lightbulb_delete.png b/kallithea/public/images/icons/lightbulb_delete.png rename from rhodecode/public/images/icons/lightbulb_delete.png rename to kallithea/public/images/icons/lightbulb_delete.png diff --git a/rhodecode/public/images/icons/lightbulb_off.png b/kallithea/public/images/icons/lightbulb_off.png rename from rhodecode/public/images/icons/lightbulb_off.png rename to kallithea/public/images/icons/lightbulb_off.png diff --git a/rhodecode/public/images/icons/lightning.png b/kallithea/public/images/icons/lightning.png rename from rhodecode/public/images/icons/lightning.png rename to kallithea/public/images/icons/lightning.png diff --git a/rhodecode/public/images/icons/lightning_add.png b/kallithea/public/images/icons/lightning_add.png rename from rhodecode/public/images/icons/lightning_add.png rename to kallithea/public/images/icons/lightning_add.png diff --git a/rhodecode/public/images/icons/lightning_delete.png b/kallithea/public/images/icons/lightning_delete.png rename from rhodecode/public/images/icons/lightning_delete.png rename to kallithea/public/images/icons/lightning_delete.png diff --git a/rhodecode/public/images/icons/lightning_go.png b/kallithea/public/images/icons/lightning_go.png rename from rhodecode/public/images/icons/lightning_go.png rename to kallithea/public/images/icons/lightning_go.png diff --git a/rhodecode/public/images/icons/link.png b/kallithea/public/images/icons/link.png rename from rhodecode/public/images/icons/link.png rename to kallithea/public/images/icons/link.png diff --git a/rhodecode/public/images/icons/link_add.png b/kallithea/public/images/icons/link_add.png rename from rhodecode/public/images/icons/link_add.png rename to kallithea/public/images/icons/link_add.png diff --git a/rhodecode/public/images/icons/link_break.png b/kallithea/public/images/icons/link_break.png rename from rhodecode/public/images/icons/link_break.png rename to kallithea/public/images/icons/link_break.png diff --git a/rhodecode/public/images/icons/link_delete.png b/kallithea/public/images/icons/link_delete.png rename from rhodecode/public/images/icons/link_delete.png rename to kallithea/public/images/icons/link_delete.png diff --git a/rhodecode/public/images/icons/link_edit.png b/kallithea/public/images/icons/link_edit.png rename from rhodecode/public/images/icons/link_edit.png rename to kallithea/public/images/icons/link_edit.png diff --git a/rhodecode/public/images/icons/link_error.png b/kallithea/public/images/icons/link_error.png rename from rhodecode/public/images/icons/link_error.png rename to kallithea/public/images/icons/link_error.png diff --git a/rhodecode/public/images/icons/link_go.png b/kallithea/public/images/icons/link_go.png rename from rhodecode/public/images/icons/link_go.png rename to kallithea/public/images/icons/link_go.png diff --git a/rhodecode/public/images/icons/lock.png b/kallithea/public/images/icons/lock.png rename from rhodecode/public/images/icons/lock.png rename to kallithea/public/images/icons/lock.png diff --git a/rhodecode/public/images/icons/lock_add.png b/kallithea/public/images/icons/lock_add.png rename from rhodecode/public/images/icons/lock_add.png rename to kallithea/public/images/icons/lock_add.png diff --git a/rhodecode/public/images/icons/lock_break.png b/kallithea/public/images/icons/lock_break.png rename from rhodecode/public/images/icons/lock_break.png rename to kallithea/public/images/icons/lock_break.png diff --git a/rhodecode/public/images/icons/lock_delete.png b/kallithea/public/images/icons/lock_delete.png rename from rhodecode/public/images/icons/lock_delete.png rename to kallithea/public/images/icons/lock_delete.png diff --git a/rhodecode/public/images/icons/lock_edit.png b/kallithea/public/images/icons/lock_edit.png rename from rhodecode/public/images/icons/lock_edit.png rename to kallithea/public/images/icons/lock_edit.png diff --git a/rhodecode/public/images/icons/lock_go.png b/kallithea/public/images/icons/lock_go.png rename from rhodecode/public/images/icons/lock_go.png rename to kallithea/public/images/icons/lock_go.png diff --git a/rhodecode/public/images/icons/lock_open.png b/kallithea/public/images/icons/lock_open.png rename from rhodecode/public/images/icons/lock_open.png rename to kallithea/public/images/icons/lock_open.png diff --git a/rhodecode/public/images/icons/lorry.png b/kallithea/public/images/icons/lorry.png rename from rhodecode/public/images/icons/lorry.png rename to kallithea/public/images/icons/lorry.png diff --git a/rhodecode/public/images/icons/lorry_add.png b/kallithea/public/images/icons/lorry_add.png rename from rhodecode/public/images/icons/lorry_add.png rename to kallithea/public/images/icons/lorry_add.png diff --git a/rhodecode/public/images/icons/lorry_delete.png b/kallithea/public/images/icons/lorry_delete.png rename from rhodecode/public/images/icons/lorry_delete.png rename to kallithea/public/images/icons/lorry_delete.png diff --git a/rhodecode/public/images/icons/lorry_error.png b/kallithea/public/images/icons/lorry_error.png rename from rhodecode/public/images/icons/lorry_error.png rename to kallithea/public/images/icons/lorry_error.png diff --git a/rhodecode/public/images/icons/lorry_flatbed.png b/kallithea/public/images/icons/lorry_flatbed.png rename from rhodecode/public/images/icons/lorry_flatbed.png rename to kallithea/public/images/icons/lorry_flatbed.png diff --git a/rhodecode/public/images/icons/lorry_go.png b/kallithea/public/images/icons/lorry_go.png rename from rhodecode/public/images/icons/lorry_go.png rename to kallithea/public/images/icons/lorry_go.png diff --git a/rhodecode/public/images/icons/lorry_link.png b/kallithea/public/images/icons/lorry_link.png rename from rhodecode/public/images/icons/lorry_link.png rename to kallithea/public/images/icons/lorry_link.png diff --git a/rhodecode/public/images/icons/magifier_zoom_out.png b/kallithea/public/images/icons/magifier_zoom_out.png rename from rhodecode/public/images/icons/magifier_zoom_out.png rename to kallithea/public/images/icons/magifier_zoom_out.png diff --git a/rhodecode/public/images/icons/magnifier.png b/kallithea/public/images/icons/magnifier.png rename from rhodecode/public/images/icons/magnifier.png rename to kallithea/public/images/icons/magnifier.png diff --git a/rhodecode/public/images/icons/magnifier_zoom_in.png b/kallithea/public/images/icons/magnifier_zoom_in.png rename from rhodecode/public/images/icons/magnifier_zoom_in.png rename to kallithea/public/images/icons/magnifier_zoom_in.png diff --git a/rhodecode/public/images/icons/male.png b/kallithea/public/images/icons/male.png rename from rhodecode/public/images/icons/male.png rename to kallithea/public/images/icons/male.png diff --git a/rhodecode/public/images/icons/map.png b/kallithea/public/images/icons/map.png rename from rhodecode/public/images/icons/map.png rename to kallithea/public/images/icons/map.png diff --git a/rhodecode/public/images/icons/map_add.png b/kallithea/public/images/icons/map_add.png rename from rhodecode/public/images/icons/map_add.png rename to kallithea/public/images/icons/map_add.png diff --git a/rhodecode/public/images/icons/map_delete.png b/kallithea/public/images/icons/map_delete.png rename from rhodecode/public/images/icons/map_delete.png rename to kallithea/public/images/icons/map_delete.png diff --git a/rhodecode/public/images/icons/map_edit.png b/kallithea/public/images/icons/map_edit.png rename from rhodecode/public/images/icons/map_edit.png rename to kallithea/public/images/icons/map_edit.png diff --git a/rhodecode/public/images/icons/map_go.png b/kallithea/public/images/icons/map_go.png rename from rhodecode/public/images/icons/map_go.png rename to kallithea/public/images/icons/map_go.png diff --git a/rhodecode/public/images/icons/map_magnify.png b/kallithea/public/images/icons/map_magnify.png rename from rhodecode/public/images/icons/map_magnify.png rename to kallithea/public/images/icons/map_magnify.png diff --git a/rhodecode/public/images/icons/medal_bronze_1.png b/kallithea/public/images/icons/medal_bronze_1.png rename from rhodecode/public/images/icons/medal_bronze_1.png rename to kallithea/public/images/icons/medal_bronze_1.png diff --git a/rhodecode/public/images/icons/medal_bronze_2.png b/kallithea/public/images/icons/medal_bronze_2.png rename from rhodecode/public/images/icons/medal_bronze_2.png rename to kallithea/public/images/icons/medal_bronze_2.png diff --git a/rhodecode/public/images/icons/medal_bronze_3.png b/kallithea/public/images/icons/medal_bronze_3.png rename from rhodecode/public/images/icons/medal_bronze_3.png rename to kallithea/public/images/icons/medal_bronze_3.png diff --git a/rhodecode/public/images/icons/medal_bronze_add.png b/kallithea/public/images/icons/medal_bronze_add.png rename from rhodecode/public/images/icons/medal_bronze_add.png rename to kallithea/public/images/icons/medal_bronze_add.png diff --git a/rhodecode/public/images/icons/medal_bronze_delete.png b/kallithea/public/images/icons/medal_bronze_delete.png rename from rhodecode/public/images/icons/medal_bronze_delete.png rename to kallithea/public/images/icons/medal_bronze_delete.png diff --git a/rhodecode/public/images/icons/medal_gold_1.png b/kallithea/public/images/icons/medal_gold_1.png rename from rhodecode/public/images/icons/medal_gold_1.png rename to kallithea/public/images/icons/medal_gold_1.png diff --git a/rhodecode/public/images/icons/medal_gold_2.png b/kallithea/public/images/icons/medal_gold_2.png rename from rhodecode/public/images/icons/medal_gold_2.png rename to kallithea/public/images/icons/medal_gold_2.png diff --git a/rhodecode/public/images/icons/medal_gold_3.png b/kallithea/public/images/icons/medal_gold_3.png rename from rhodecode/public/images/icons/medal_gold_3.png rename to kallithea/public/images/icons/medal_gold_3.png diff --git a/rhodecode/public/images/icons/medal_gold_add.png b/kallithea/public/images/icons/medal_gold_add.png rename from rhodecode/public/images/icons/medal_gold_add.png rename to kallithea/public/images/icons/medal_gold_add.png diff --git a/rhodecode/public/images/icons/medal_gold_delete.png b/kallithea/public/images/icons/medal_gold_delete.png rename from rhodecode/public/images/icons/medal_gold_delete.png rename to kallithea/public/images/icons/medal_gold_delete.png diff --git a/rhodecode/public/images/icons/medal_silver_1.png b/kallithea/public/images/icons/medal_silver_1.png rename from rhodecode/public/images/icons/medal_silver_1.png rename to kallithea/public/images/icons/medal_silver_1.png diff --git a/rhodecode/public/images/icons/medal_silver_2.png b/kallithea/public/images/icons/medal_silver_2.png rename from rhodecode/public/images/icons/medal_silver_2.png rename to kallithea/public/images/icons/medal_silver_2.png diff --git a/rhodecode/public/images/icons/medal_silver_3.png b/kallithea/public/images/icons/medal_silver_3.png rename from rhodecode/public/images/icons/medal_silver_3.png rename to kallithea/public/images/icons/medal_silver_3.png diff --git a/rhodecode/public/images/icons/medal_silver_add.png b/kallithea/public/images/icons/medal_silver_add.png rename from rhodecode/public/images/icons/medal_silver_add.png rename to kallithea/public/images/icons/medal_silver_add.png diff --git a/rhodecode/public/images/icons/medal_silver_delete.png b/kallithea/public/images/icons/medal_silver_delete.png rename from rhodecode/public/images/icons/medal_silver_delete.png rename to kallithea/public/images/icons/medal_silver_delete.png diff --git a/rhodecode/public/images/icons/money.png b/kallithea/public/images/icons/money.png rename from rhodecode/public/images/icons/money.png rename to kallithea/public/images/icons/money.png diff --git a/rhodecode/public/images/icons/money_add.png b/kallithea/public/images/icons/money_add.png rename from rhodecode/public/images/icons/money_add.png rename to kallithea/public/images/icons/money_add.png diff --git a/rhodecode/public/images/icons/money_delete.png b/kallithea/public/images/icons/money_delete.png rename from rhodecode/public/images/icons/money_delete.png rename to kallithea/public/images/icons/money_delete.png diff --git a/rhodecode/public/images/icons/money_dollar.png b/kallithea/public/images/icons/money_dollar.png rename from rhodecode/public/images/icons/money_dollar.png rename to kallithea/public/images/icons/money_dollar.png diff --git a/rhodecode/public/images/icons/money_euro.png b/kallithea/public/images/icons/money_euro.png rename from rhodecode/public/images/icons/money_euro.png rename to kallithea/public/images/icons/money_euro.png diff --git a/rhodecode/public/images/icons/money_pound.png b/kallithea/public/images/icons/money_pound.png rename from rhodecode/public/images/icons/money_pound.png rename to kallithea/public/images/icons/money_pound.png diff --git a/rhodecode/public/images/icons/money_yen.png b/kallithea/public/images/icons/money_yen.png rename from rhodecode/public/images/icons/money_yen.png rename to kallithea/public/images/icons/money_yen.png diff --git a/rhodecode/public/images/icons/monitor.png b/kallithea/public/images/icons/monitor.png rename from rhodecode/public/images/icons/monitor.png rename to kallithea/public/images/icons/monitor.png diff --git a/rhodecode/public/images/icons/monitor_16.png b/kallithea/public/images/icons/monitor_16.png rename from rhodecode/public/images/icons/monitor_16.png rename to kallithea/public/images/icons/monitor_16.png diff --git a/rhodecode/public/images/icons/monitor_add.png b/kallithea/public/images/icons/monitor_add.png rename from rhodecode/public/images/icons/monitor_add.png rename to kallithea/public/images/icons/monitor_add.png diff --git a/rhodecode/public/images/icons/monitor_delete.png b/kallithea/public/images/icons/monitor_delete.png rename from rhodecode/public/images/icons/monitor_delete.png rename to kallithea/public/images/icons/monitor_delete.png diff --git a/rhodecode/public/images/icons/monitor_edit.png b/kallithea/public/images/icons/monitor_edit.png rename from rhodecode/public/images/icons/monitor_edit.png rename to kallithea/public/images/icons/monitor_edit.png diff --git a/rhodecode/public/images/icons/monitor_error.png b/kallithea/public/images/icons/monitor_error.png rename from rhodecode/public/images/icons/monitor_error.png rename to kallithea/public/images/icons/monitor_error.png diff --git a/rhodecode/public/images/icons/monitor_go.png b/kallithea/public/images/icons/monitor_go.png rename from rhodecode/public/images/icons/monitor_go.png rename to kallithea/public/images/icons/monitor_go.png diff --git a/rhodecode/public/images/icons/monitor_lightning.png b/kallithea/public/images/icons/monitor_lightning.png rename from rhodecode/public/images/icons/monitor_lightning.png rename to kallithea/public/images/icons/monitor_lightning.png diff --git a/rhodecode/public/images/icons/monitor_link.png b/kallithea/public/images/icons/monitor_link.png rename from rhodecode/public/images/icons/monitor_link.png rename to kallithea/public/images/icons/monitor_link.png diff --git a/rhodecode/public/images/icons/mouse.png b/kallithea/public/images/icons/mouse.png rename from rhodecode/public/images/icons/mouse.png rename to kallithea/public/images/icons/mouse.png diff --git a/rhodecode/public/images/icons/mouse_add.png b/kallithea/public/images/icons/mouse_add.png rename from rhodecode/public/images/icons/mouse_add.png rename to kallithea/public/images/icons/mouse_add.png diff --git a/rhodecode/public/images/icons/mouse_delete.png b/kallithea/public/images/icons/mouse_delete.png rename from rhodecode/public/images/icons/mouse_delete.png rename to kallithea/public/images/icons/mouse_delete.png diff --git a/rhodecode/public/images/icons/mouse_error.png b/kallithea/public/images/icons/mouse_error.png rename from rhodecode/public/images/icons/mouse_error.png rename to kallithea/public/images/icons/mouse_error.png diff --git a/rhodecode/public/images/icons/music.png b/kallithea/public/images/icons/music.png rename from rhodecode/public/images/icons/music.png rename to kallithea/public/images/icons/music.png diff --git a/rhodecode/public/images/icons/new.png b/kallithea/public/images/icons/new.png rename from rhodecode/public/images/icons/new.png rename to kallithea/public/images/icons/new.png diff --git a/rhodecode/public/images/icons/newspaper.png b/kallithea/public/images/icons/newspaper.png rename from rhodecode/public/images/icons/newspaper.png rename to kallithea/public/images/icons/newspaper.png diff --git a/rhodecode/public/images/icons/newspaper_add.png b/kallithea/public/images/icons/newspaper_add.png rename from rhodecode/public/images/icons/newspaper_add.png rename to kallithea/public/images/icons/newspaper_add.png diff --git a/rhodecode/public/images/icons/newspaper_delete.png b/kallithea/public/images/icons/newspaper_delete.png rename from rhodecode/public/images/icons/newspaper_delete.png rename to kallithea/public/images/icons/newspaper_delete.png diff --git a/rhodecode/public/images/icons/newspaper_go.png b/kallithea/public/images/icons/newspaper_go.png rename from rhodecode/public/images/icons/newspaper_go.png rename to kallithea/public/images/icons/newspaper_go.png diff --git a/rhodecode/public/images/icons/newspaper_link.png b/kallithea/public/images/icons/newspaper_link.png rename from rhodecode/public/images/icons/newspaper_link.png rename to kallithea/public/images/icons/newspaper_link.png diff --git a/rhodecode/public/images/icons/note.png b/kallithea/public/images/icons/note.png rename from rhodecode/public/images/icons/note.png rename to kallithea/public/images/icons/note.png diff --git a/rhodecode/public/images/icons/note_add.png b/kallithea/public/images/icons/note_add.png rename from rhodecode/public/images/icons/note_add.png rename to kallithea/public/images/icons/note_add.png diff --git a/rhodecode/public/images/icons/note_delete.png b/kallithea/public/images/icons/note_delete.png rename from rhodecode/public/images/icons/note_delete.png rename to kallithea/public/images/icons/note_delete.png diff --git a/rhodecode/public/images/icons/note_edit.png b/kallithea/public/images/icons/note_edit.png rename from rhodecode/public/images/icons/note_edit.png rename to kallithea/public/images/icons/note_edit.png diff --git a/rhodecode/public/images/icons/note_error.png b/kallithea/public/images/icons/note_error.png rename from rhodecode/public/images/icons/note_error.png rename to kallithea/public/images/icons/note_error.png diff --git a/rhodecode/public/images/icons/note_go.png b/kallithea/public/images/icons/note_go.png rename from rhodecode/public/images/icons/note_go.png rename to kallithea/public/images/icons/note_go.png diff --git a/rhodecode/public/images/icons/notice_msg.png b/kallithea/public/images/icons/notice_msg.png rename from rhodecode/public/images/icons/notice_msg.png rename to kallithea/public/images/icons/notice_msg.png diff --git a/rhodecode/public/images/icons/overlays.png b/kallithea/public/images/icons/overlays.png rename from rhodecode/public/images/icons/overlays.png rename to kallithea/public/images/icons/overlays.png diff --git a/rhodecode/public/images/icons/package.png b/kallithea/public/images/icons/package.png rename from rhodecode/public/images/icons/package.png rename to kallithea/public/images/icons/package.png diff --git a/rhodecode/public/images/icons/package_add.png b/kallithea/public/images/icons/package_add.png rename from rhodecode/public/images/icons/package_add.png rename to kallithea/public/images/icons/package_add.png diff --git a/rhodecode/public/images/icons/package_delete.png b/kallithea/public/images/icons/package_delete.png rename from rhodecode/public/images/icons/package_delete.png rename to kallithea/public/images/icons/package_delete.png diff --git a/rhodecode/public/images/icons/package_go.png b/kallithea/public/images/icons/package_go.png rename from rhodecode/public/images/icons/package_go.png rename to kallithea/public/images/icons/package_go.png diff --git a/rhodecode/public/images/icons/package_green.png b/kallithea/public/images/icons/package_green.png rename from rhodecode/public/images/icons/package_green.png rename to kallithea/public/images/icons/package_green.png diff --git a/rhodecode/public/images/icons/package_link.png b/kallithea/public/images/icons/package_link.png rename from rhodecode/public/images/icons/package_link.png rename to kallithea/public/images/icons/package_link.png diff --git a/rhodecode/public/images/icons/page.png b/kallithea/public/images/icons/page.png rename from rhodecode/public/images/icons/page.png rename to kallithea/public/images/icons/page.png diff --git a/rhodecode/public/images/icons/page_add.png b/kallithea/public/images/icons/page_add.png rename from rhodecode/public/images/icons/page_add.png rename to kallithea/public/images/icons/page_add.png diff --git a/rhodecode/public/images/icons/page_attach.png b/kallithea/public/images/icons/page_attach.png rename from rhodecode/public/images/icons/page_attach.png rename to kallithea/public/images/icons/page_attach.png diff --git a/rhodecode/public/images/icons/page_code.png b/kallithea/public/images/icons/page_code.png rename from rhodecode/public/images/icons/page_code.png rename to kallithea/public/images/icons/page_code.png diff --git a/rhodecode/public/images/icons/page_copy.png b/kallithea/public/images/icons/page_copy.png rename from rhodecode/public/images/icons/page_copy.png rename to kallithea/public/images/icons/page_copy.png diff --git a/rhodecode/public/images/icons/page_delete.png b/kallithea/public/images/icons/page_delete.png rename from rhodecode/public/images/icons/page_delete.png rename to kallithea/public/images/icons/page_delete.png diff --git a/rhodecode/public/images/icons/page_edit.png b/kallithea/public/images/icons/page_edit.png rename from rhodecode/public/images/icons/page_edit.png rename to kallithea/public/images/icons/page_edit.png diff --git a/rhodecode/public/images/icons/page_error.png b/kallithea/public/images/icons/page_error.png rename from rhodecode/public/images/icons/page_error.png rename to kallithea/public/images/icons/page_error.png diff --git a/rhodecode/public/images/icons/page_excel.png b/kallithea/public/images/icons/page_excel.png rename from rhodecode/public/images/icons/page_excel.png rename to kallithea/public/images/icons/page_excel.png diff --git a/rhodecode/public/images/icons/page_find.png b/kallithea/public/images/icons/page_find.png rename from rhodecode/public/images/icons/page_find.png rename to kallithea/public/images/icons/page_find.png diff --git a/rhodecode/public/images/icons/page_gear.png b/kallithea/public/images/icons/page_gear.png rename from rhodecode/public/images/icons/page_gear.png rename to kallithea/public/images/icons/page_gear.png diff --git a/rhodecode/public/images/icons/page_go.png b/kallithea/public/images/icons/page_go.png rename from rhodecode/public/images/icons/page_go.png rename to kallithea/public/images/icons/page_go.png diff --git a/rhodecode/public/images/icons/page_green.png b/kallithea/public/images/icons/page_green.png rename from rhodecode/public/images/icons/page_green.png rename to kallithea/public/images/icons/page_green.png diff --git a/rhodecode/public/images/icons/page_key.png b/kallithea/public/images/icons/page_key.png rename from rhodecode/public/images/icons/page_key.png rename to kallithea/public/images/icons/page_key.png diff --git a/rhodecode/public/images/icons/page_lightning.png b/kallithea/public/images/icons/page_lightning.png rename from rhodecode/public/images/icons/page_lightning.png rename to kallithea/public/images/icons/page_lightning.png diff --git a/rhodecode/public/images/icons/page_link.png b/kallithea/public/images/icons/page_link.png rename from rhodecode/public/images/icons/page_link.png rename to kallithea/public/images/icons/page_link.png diff --git a/rhodecode/public/images/icons/page_paintbrush.png b/kallithea/public/images/icons/page_paintbrush.png rename from rhodecode/public/images/icons/page_paintbrush.png rename to kallithea/public/images/icons/page_paintbrush.png diff --git a/rhodecode/public/images/icons/page_paste.png b/kallithea/public/images/icons/page_paste.png rename from rhodecode/public/images/icons/page_paste.png rename to kallithea/public/images/icons/page_paste.png diff --git a/rhodecode/public/images/icons/page_red.png b/kallithea/public/images/icons/page_red.png rename from rhodecode/public/images/icons/page_red.png rename to kallithea/public/images/icons/page_red.png diff --git a/rhodecode/public/images/icons/page_refresh.png b/kallithea/public/images/icons/page_refresh.png rename from rhodecode/public/images/icons/page_refresh.png rename to kallithea/public/images/icons/page_refresh.png diff --git a/rhodecode/public/images/icons/page_save.png b/kallithea/public/images/icons/page_save.png rename from rhodecode/public/images/icons/page_save.png rename to kallithea/public/images/icons/page_save.png diff --git a/rhodecode/public/images/icons/page_white.png b/kallithea/public/images/icons/page_white.png rename from rhodecode/public/images/icons/page_white.png rename to kallithea/public/images/icons/page_white.png diff --git a/rhodecode/public/images/icons/page_white_acrobat.png b/kallithea/public/images/icons/page_white_acrobat.png rename from rhodecode/public/images/icons/page_white_acrobat.png rename to kallithea/public/images/icons/page_white_acrobat.png diff --git a/rhodecode/public/images/icons/page_white_actionscript.png b/kallithea/public/images/icons/page_white_actionscript.png rename from rhodecode/public/images/icons/page_white_actionscript.png rename to kallithea/public/images/icons/page_white_actionscript.png diff --git a/rhodecode/public/images/icons/page_white_add.png b/kallithea/public/images/icons/page_white_add.png rename from rhodecode/public/images/icons/page_white_add.png rename to kallithea/public/images/icons/page_white_add.png diff --git a/rhodecode/public/images/icons/page_white_c.png b/kallithea/public/images/icons/page_white_c.png rename from rhodecode/public/images/icons/page_white_c.png rename to kallithea/public/images/icons/page_white_c.png diff --git a/rhodecode/public/images/icons/page_white_camera.png b/kallithea/public/images/icons/page_white_camera.png rename from rhodecode/public/images/icons/page_white_camera.png rename to kallithea/public/images/icons/page_white_camera.png diff --git a/rhodecode/public/images/icons/page_white_cd.png b/kallithea/public/images/icons/page_white_cd.png rename from rhodecode/public/images/icons/page_white_cd.png rename to kallithea/public/images/icons/page_white_cd.png diff --git a/rhodecode/public/images/icons/page_white_code.png b/kallithea/public/images/icons/page_white_code.png rename from rhodecode/public/images/icons/page_white_code.png rename to kallithea/public/images/icons/page_white_code.png diff --git a/rhodecode/public/images/icons/page_white_code_red.png b/kallithea/public/images/icons/page_white_code_red.png rename from rhodecode/public/images/icons/page_white_code_red.png rename to kallithea/public/images/icons/page_white_code_red.png diff --git a/rhodecode/public/images/icons/page_white_coldfusion.png b/kallithea/public/images/icons/page_white_coldfusion.png rename from rhodecode/public/images/icons/page_white_coldfusion.png rename to kallithea/public/images/icons/page_white_coldfusion.png diff --git a/rhodecode/public/images/icons/page_white_compressed.png b/kallithea/public/images/icons/page_white_compressed.png rename from rhodecode/public/images/icons/page_white_compressed.png rename to kallithea/public/images/icons/page_white_compressed.png diff --git a/rhodecode/public/images/icons/page_white_copy.png b/kallithea/public/images/icons/page_white_copy.png rename from rhodecode/public/images/icons/page_white_copy.png rename to kallithea/public/images/icons/page_white_copy.png diff --git a/rhodecode/public/images/icons/page_white_cplusplus.png b/kallithea/public/images/icons/page_white_cplusplus.png rename from rhodecode/public/images/icons/page_white_cplusplus.png rename to kallithea/public/images/icons/page_white_cplusplus.png diff --git a/rhodecode/public/images/icons/page_white_csharp.png b/kallithea/public/images/icons/page_white_csharp.png rename from rhodecode/public/images/icons/page_white_csharp.png rename to kallithea/public/images/icons/page_white_csharp.png diff --git a/rhodecode/public/images/icons/page_white_cup.png b/kallithea/public/images/icons/page_white_cup.png rename from rhodecode/public/images/icons/page_white_cup.png rename to kallithea/public/images/icons/page_white_cup.png diff --git a/rhodecode/public/images/icons/page_white_database.png b/kallithea/public/images/icons/page_white_database.png rename from rhodecode/public/images/icons/page_white_database.png rename to kallithea/public/images/icons/page_white_database.png diff --git a/rhodecode/public/images/icons/page_white_delete.png b/kallithea/public/images/icons/page_white_delete.png rename from rhodecode/public/images/icons/page_white_delete.png rename to kallithea/public/images/icons/page_white_delete.png diff --git a/rhodecode/public/images/icons/page_white_dvd.png b/kallithea/public/images/icons/page_white_dvd.png rename from rhodecode/public/images/icons/page_white_dvd.png rename to kallithea/public/images/icons/page_white_dvd.png diff --git a/rhodecode/public/images/icons/page_white_edit.png b/kallithea/public/images/icons/page_white_edit.png rename from rhodecode/public/images/icons/page_white_edit.png rename to kallithea/public/images/icons/page_white_edit.png diff --git a/rhodecode/public/images/icons/page_white_error.png b/kallithea/public/images/icons/page_white_error.png rename from rhodecode/public/images/icons/page_white_error.png rename to kallithea/public/images/icons/page_white_error.png diff --git a/rhodecode/public/images/icons/page_white_excel.png b/kallithea/public/images/icons/page_white_excel.png rename from rhodecode/public/images/icons/page_white_excel.png rename to kallithea/public/images/icons/page_white_excel.png diff --git a/rhodecode/public/images/icons/page_white_find.png b/kallithea/public/images/icons/page_white_find.png rename from rhodecode/public/images/icons/page_white_find.png rename to kallithea/public/images/icons/page_white_find.png diff --git a/rhodecode/public/images/icons/page_white_flash.png b/kallithea/public/images/icons/page_white_flash.png rename from rhodecode/public/images/icons/page_white_flash.png rename to kallithea/public/images/icons/page_white_flash.png diff --git a/rhodecode/public/images/icons/page_white_freehand.png b/kallithea/public/images/icons/page_white_freehand.png rename from rhodecode/public/images/icons/page_white_freehand.png rename to kallithea/public/images/icons/page_white_freehand.png diff --git a/rhodecode/public/images/icons/page_white_gear.png b/kallithea/public/images/icons/page_white_gear.png rename from rhodecode/public/images/icons/page_white_gear.png rename to kallithea/public/images/icons/page_white_gear.png diff --git a/rhodecode/public/images/icons/page_white_get.png b/kallithea/public/images/icons/page_white_get.png rename from rhodecode/public/images/icons/page_white_get.png rename to kallithea/public/images/icons/page_white_get.png diff --git a/rhodecode/public/images/icons/page_white_go.png b/kallithea/public/images/icons/page_white_go.png rename from rhodecode/public/images/icons/page_white_go.png rename to kallithea/public/images/icons/page_white_go.png diff --git a/rhodecode/public/images/icons/page_white_h.png b/kallithea/public/images/icons/page_white_h.png rename from rhodecode/public/images/icons/page_white_h.png rename to kallithea/public/images/icons/page_white_h.png diff --git a/rhodecode/public/images/icons/page_white_horizontal.png b/kallithea/public/images/icons/page_white_horizontal.png rename from rhodecode/public/images/icons/page_white_horizontal.png rename to kallithea/public/images/icons/page_white_horizontal.png diff --git a/rhodecode/public/images/icons/page_white_key.png b/kallithea/public/images/icons/page_white_key.png rename from rhodecode/public/images/icons/page_white_key.png rename to kallithea/public/images/icons/page_white_key.png diff --git a/rhodecode/public/images/icons/page_white_lightning.png b/kallithea/public/images/icons/page_white_lightning.png rename from rhodecode/public/images/icons/page_white_lightning.png rename to kallithea/public/images/icons/page_white_lightning.png diff --git a/rhodecode/public/images/icons/page_white_link.png b/kallithea/public/images/icons/page_white_link.png rename from rhodecode/public/images/icons/page_white_link.png rename to kallithea/public/images/icons/page_white_link.png diff --git a/rhodecode/public/images/icons/page_white_magnify.png b/kallithea/public/images/icons/page_white_magnify.png rename from rhodecode/public/images/icons/page_white_magnify.png rename to kallithea/public/images/icons/page_white_magnify.png diff --git a/rhodecode/public/images/icons/page_white_medal.png b/kallithea/public/images/icons/page_white_medal.png rename from rhodecode/public/images/icons/page_white_medal.png rename to kallithea/public/images/icons/page_white_medal.png diff --git a/rhodecode/public/images/icons/page_white_office.png b/kallithea/public/images/icons/page_white_office.png rename from rhodecode/public/images/icons/page_white_office.png rename to kallithea/public/images/icons/page_white_office.png diff --git a/rhodecode/public/images/icons/page_white_paint.png b/kallithea/public/images/icons/page_white_paint.png rename from rhodecode/public/images/icons/page_white_paint.png rename to kallithea/public/images/icons/page_white_paint.png diff --git a/rhodecode/public/images/icons/page_white_paintbrush.png b/kallithea/public/images/icons/page_white_paintbrush.png rename from rhodecode/public/images/icons/page_white_paintbrush.png rename to kallithea/public/images/icons/page_white_paintbrush.png diff --git a/rhodecode/public/images/icons/page_white_paste.png b/kallithea/public/images/icons/page_white_paste.png rename from rhodecode/public/images/icons/page_white_paste.png rename to kallithea/public/images/icons/page_white_paste.png diff --git a/rhodecode/public/images/icons/page_white_php.png b/kallithea/public/images/icons/page_white_php.png rename from rhodecode/public/images/icons/page_white_php.png rename to kallithea/public/images/icons/page_white_php.png diff --git a/rhodecode/public/images/icons/page_white_picture.png b/kallithea/public/images/icons/page_white_picture.png rename from rhodecode/public/images/icons/page_white_picture.png rename to kallithea/public/images/icons/page_white_picture.png diff --git a/rhodecode/public/images/icons/page_white_powerpoint.png b/kallithea/public/images/icons/page_white_powerpoint.png rename from rhodecode/public/images/icons/page_white_powerpoint.png rename to kallithea/public/images/icons/page_white_powerpoint.png diff --git a/rhodecode/public/images/icons/page_white_put.png b/kallithea/public/images/icons/page_white_put.png rename from rhodecode/public/images/icons/page_white_put.png rename to kallithea/public/images/icons/page_white_put.png diff --git a/rhodecode/public/images/icons/page_white_ruby.png b/kallithea/public/images/icons/page_white_ruby.png rename from rhodecode/public/images/icons/page_white_ruby.png rename to kallithea/public/images/icons/page_white_ruby.png diff --git a/rhodecode/public/images/icons/page_white_stack.png b/kallithea/public/images/icons/page_white_stack.png rename from rhodecode/public/images/icons/page_white_stack.png rename to kallithea/public/images/icons/page_white_stack.png diff --git a/rhodecode/public/images/icons/page_white_star.png b/kallithea/public/images/icons/page_white_star.png rename from rhodecode/public/images/icons/page_white_star.png rename to kallithea/public/images/icons/page_white_star.png diff --git a/rhodecode/public/images/icons/page_white_swoosh.png b/kallithea/public/images/icons/page_white_swoosh.png rename from rhodecode/public/images/icons/page_white_swoosh.png rename to kallithea/public/images/icons/page_white_swoosh.png diff --git a/rhodecode/public/images/icons/page_white_text.png b/kallithea/public/images/icons/page_white_text.png rename from rhodecode/public/images/icons/page_white_text.png rename to kallithea/public/images/icons/page_white_text.png diff --git a/rhodecode/public/images/icons/page_white_text_width.png b/kallithea/public/images/icons/page_white_text_width.png rename from rhodecode/public/images/icons/page_white_text_width.png rename to kallithea/public/images/icons/page_white_text_width.png diff --git a/rhodecode/public/images/icons/page_white_tux.png b/kallithea/public/images/icons/page_white_tux.png rename from rhodecode/public/images/icons/page_white_tux.png rename to kallithea/public/images/icons/page_white_tux.png diff --git a/rhodecode/public/images/icons/page_white_vector.png b/kallithea/public/images/icons/page_white_vector.png rename from rhodecode/public/images/icons/page_white_vector.png rename to kallithea/public/images/icons/page_white_vector.png diff --git a/rhodecode/public/images/icons/page_white_visualstudio.png b/kallithea/public/images/icons/page_white_visualstudio.png rename from rhodecode/public/images/icons/page_white_visualstudio.png rename to kallithea/public/images/icons/page_white_visualstudio.png diff --git a/rhodecode/public/images/icons/page_white_width.png b/kallithea/public/images/icons/page_white_width.png rename from rhodecode/public/images/icons/page_white_width.png rename to kallithea/public/images/icons/page_white_width.png diff --git a/rhodecode/public/images/icons/page_white_word.png b/kallithea/public/images/icons/page_white_word.png rename from rhodecode/public/images/icons/page_white_word.png rename to kallithea/public/images/icons/page_white_word.png diff --git a/rhodecode/public/images/icons/page_white_world.png b/kallithea/public/images/icons/page_white_world.png rename from rhodecode/public/images/icons/page_white_world.png rename to kallithea/public/images/icons/page_white_world.png diff --git a/rhodecode/public/images/icons/page_white_wrench.png b/kallithea/public/images/icons/page_white_wrench.png rename from rhodecode/public/images/icons/page_white_wrench.png rename to kallithea/public/images/icons/page_white_wrench.png diff --git a/rhodecode/public/images/icons/page_white_zip.png b/kallithea/public/images/icons/page_white_zip.png rename from rhodecode/public/images/icons/page_white_zip.png rename to kallithea/public/images/icons/page_white_zip.png diff --git a/rhodecode/public/images/icons/page_word.png b/kallithea/public/images/icons/page_word.png rename from rhodecode/public/images/icons/page_word.png rename to kallithea/public/images/icons/page_word.png diff --git a/rhodecode/public/images/icons/page_world.png b/kallithea/public/images/icons/page_world.png rename from rhodecode/public/images/icons/page_world.png rename to kallithea/public/images/icons/page_world.png diff --git a/rhodecode/public/images/icons/paintbrush.png b/kallithea/public/images/icons/paintbrush.png rename from rhodecode/public/images/icons/paintbrush.png rename to kallithea/public/images/icons/paintbrush.png diff --git a/rhodecode/public/images/icons/paintcan.png b/kallithea/public/images/icons/paintcan.png rename from rhodecode/public/images/icons/paintcan.png rename to kallithea/public/images/icons/paintcan.png diff --git a/rhodecode/public/images/icons/palette.png b/kallithea/public/images/icons/palette.png rename from rhodecode/public/images/icons/palette.png rename to kallithea/public/images/icons/palette.png diff --git a/rhodecode/public/images/icons/paste_plain.png b/kallithea/public/images/icons/paste_plain.png rename from rhodecode/public/images/icons/paste_plain.png rename to kallithea/public/images/icons/paste_plain.png diff --git a/rhodecode/public/images/icons/paste_word.png b/kallithea/public/images/icons/paste_word.png rename from rhodecode/public/images/icons/paste_word.png rename to kallithea/public/images/icons/paste_word.png diff --git a/rhodecode/public/images/icons/pencil.png b/kallithea/public/images/icons/pencil.png rename from rhodecode/public/images/icons/pencil.png rename to kallithea/public/images/icons/pencil.png diff --git a/rhodecode/public/images/icons/pencil_16.png b/kallithea/public/images/icons/pencil_16.png rename from rhodecode/public/images/icons/pencil_16.png rename to kallithea/public/images/icons/pencil_16.png diff --git a/rhodecode/public/images/icons/pencil_add.png b/kallithea/public/images/icons/pencil_add.png rename from rhodecode/public/images/icons/pencil_add.png rename to kallithea/public/images/icons/pencil_add.png diff --git a/rhodecode/public/images/icons/pencil_delete.png b/kallithea/public/images/icons/pencil_delete.png rename from rhodecode/public/images/icons/pencil_delete.png rename to kallithea/public/images/icons/pencil_delete.png diff --git a/rhodecode/public/images/icons/pencil_go.png b/kallithea/public/images/icons/pencil_go.png rename from rhodecode/public/images/icons/pencil_go.png rename to kallithea/public/images/icons/pencil_go.png diff --git a/rhodecode/public/images/icons/phone.png b/kallithea/public/images/icons/phone.png rename from rhodecode/public/images/icons/phone.png rename to kallithea/public/images/icons/phone.png diff --git a/rhodecode/public/images/icons/phone_add.png b/kallithea/public/images/icons/phone_add.png rename from rhodecode/public/images/icons/phone_add.png rename to kallithea/public/images/icons/phone_add.png diff --git a/rhodecode/public/images/icons/phone_delete.png b/kallithea/public/images/icons/phone_delete.png rename from rhodecode/public/images/icons/phone_delete.png rename to kallithea/public/images/icons/phone_delete.png diff --git a/rhodecode/public/images/icons/phone_sound.png b/kallithea/public/images/icons/phone_sound.png rename from rhodecode/public/images/icons/phone_sound.png rename to kallithea/public/images/icons/phone_sound.png diff --git a/rhodecode/public/images/icons/photo.png b/kallithea/public/images/icons/photo.png rename from rhodecode/public/images/icons/photo.png rename to kallithea/public/images/icons/photo.png diff --git a/rhodecode/public/images/icons/photo_add.png b/kallithea/public/images/icons/photo_add.png rename from rhodecode/public/images/icons/photo_add.png rename to kallithea/public/images/icons/photo_add.png diff --git a/rhodecode/public/images/icons/photo_delete.png b/kallithea/public/images/icons/photo_delete.png rename from rhodecode/public/images/icons/photo_delete.png rename to kallithea/public/images/icons/photo_delete.png diff --git a/rhodecode/public/images/icons/photo_link.png b/kallithea/public/images/icons/photo_link.png rename from rhodecode/public/images/icons/photo_link.png rename to kallithea/public/images/icons/photo_link.png diff --git a/rhodecode/public/images/icons/photos.png b/kallithea/public/images/icons/photos.png rename from rhodecode/public/images/icons/photos.png rename to kallithea/public/images/icons/photos.png diff --git a/rhodecode/public/images/icons/picture.png b/kallithea/public/images/icons/picture.png rename from rhodecode/public/images/icons/picture.png rename to kallithea/public/images/icons/picture.png diff --git a/rhodecode/public/images/icons/picture_add.png b/kallithea/public/images/icons/picture_add.png rename from rhodecode/public/images/icons/picture_add.png rename to kallithea/public/images/icons/picture_add.png diff --git a/rhodecode/public/images/icons/picture_delete.png b/kallithea/public/images/icons/picture_delete.png rename from rhodecode/public/images/icons/picture_delete.png rename to kallithea/public/images/icons/picture_delete.png diff --git a/rhodecode/public/images/icons/picture_edit.png b/kallithea/public/images/icons/picture_edit.png rename from rhodecode/public/images/icons/picture_edit.png rename to kallithea/public/images/icons/picture_edit.png diff --git a/rhodecode/public/images/icons/picture_empty.png b/kallithea/public/images/icons/picture_empty.png rename from rhodecode/public/images/icons/picture_empty.png rename to kallithea/public/images/icons/picture_empty.png diff --git a/rhodecode/public/images/icons/picture_error.png b/kallithea/public/images/icons/picture_error.png rename from rhodecode/public/images/icons/picture_error.png rename to kallithea/public/images/icons/picture_error.png diff --git a/rhodecode/public/images/icons/picture_go.png b/kallithea/public/images/icons/picture_go.png rename from rhodecode/public/images/icons/picture_go.png rename to kallithea/public/images/icons/picture_go.png diff --git a/rhodecode/public/images/icons/picture_key.png b/kallithea/public/images/icons/picture_key.png rename from rhodecode/public/images/icons/picture_key.png rename to kallithea/public/images/icons/picture_key.png diff --git a/rhodecode/public/images/icons/picture_link.png b/kallithea/public/images/icons/picture_link.png rename from rhodecode/public/images/icons/picture_link.png rename to kallithea/public/images/icons/picture_link.png diff --git a/rhodecode/public/images/icons/picture_save.png b/kallithea/public/images/icons/picture_save.png rename from rhodecode/public/images/icons/picture_save.png rename to kallithea/public/images/icons/picture_save.png diff --git a/rhodecode/public/images/icons/pictures.png b/kallithea/public/images/icons/pictures.png rename from rhodecode/public/images/icons/pictures.png rename to kallithea/public/images/icons/pictures.png diff --git a/rhodecode/public/images/icons/pilcrow.png b/kallithea/public/images/icons/pilcrow.png rename from rhodecode/public/images/icons/pilcrow.png rename to kallithea/public/images/icons/pilcrow.png diff --git a/rhodecode/public/images/icons/pill.png b/kallithea/public/images/icons/pill.png rename from rhodecode/public/images/icons/pill.png rename to kallithea/public/images/icons/pill.png diff --git a/rhodecode/public/images/icons/pill_add.png b/kallithea/public/images/icons/pill_add.png rename from rhodecode/public/images/icons/pill_add.png rename to kallithea/public/images/icons/pill_add.png diff --git a/rhodecode/public/images/icons/pill_delete.png b/kallithea/public/images/icons/pill_delete.png rename from rhodecode/public/images/icons/pill_delete.png rename to kallithea/public/images/icons/pill_delete.png diff --git a/rhodecode/public/images/icons/pill_go.png b/kallithea/public/images/icons/pill_go.png rename from rhodecode/public/images/icons/pill_go.png rename to kallithea/public/images/icons/pill_go.png diff --git a/rhodecode/public/images/icons/plugin.png b/kallithea/public/images/icons/plugin.png rename from rhodecode/public/images/icons/plugin.png rename to kallithea/public/images/icons/plugin.png diff --git a/rhodecode/public/images/icons/plugin_add.png b/kallithea/public/images/icons/plugin_add.png rename from rhodecode/public/images/icons/plugin_add.png rename to kallithea/public/images/icons/plugin_add.png diff --git a/rhodecode/public/images/icons/plugin_delete.png b/kallithea/public/images/icons/plugin_delete.png rename from rhodecode/public/images/icons/plugin_delete.png rename to kallithea/public/images/icons/plugin_delete.png diff --git a/rhodecode/public/images/icons/plugin_disabled.png b/kallithea/public/images/icons/plugin_disabled.png rename from rhodecode/public/images/icons/plugin_disabled.png rename to kallithea/public/images/icons/plugin_disabled.png diff --git a/rhodecode/public/images/icons/plugin_edit.png b/kallithea/public/images/icons/plugin_edit.png rename from rhodecode/public/images/icons/plugin_edit.png rename to kallithea/public/images/icons/plugin_edit.png diff --git a/rhodecode/public/images/icons/plugin_error.png b/kallithea/public/images/icons/plugin_error.png rename from rhodecode/public/images/icons/plugin_error.png rename to kallithea/public/images/icons/plugin_error.png diff --git a/rhodecode/public/images/icons/plugin_go.png b/kallithea/public/images/icons/plugin_go.png rename from rhodecode/public/images/icons/plugin_go.png rename to kallithea/public/images/icons/plugin_go.png diff --git a/rhodecode/public/images/icons/plugin_link.png b/kallithea/public/images/icons/plugin_link.png rename from rhodecode/public/images/icons/plugin_link.png rename to kallithea/public/images/icons/plugin_link.png diff --git a/rhodecode/public/images/icons/plus_16.png b/kallithea/public/images/icons/plus_16.png rename from rhodecode/public/images/icons/plus_16.png rename to kallithea/public/images/icons/plus_16.png diff --git a/rhodecode/public/images/icons/present_16.png b/kallithea/public/images/icons/present_16.png rename from rhodecode/public/images/icons/present_16.png rename to kallithea/public/images/icons/present_16.png diff --git a/rhodecode/public/images/icons/print_16.png b/kallithea/public/images/icons/print_16.png rename from rhodecode/public/images/icons/print_16.png rename to kallithea/public/images/icons/print_16.png diff --git a/rhodecode/public/images/icons/printer.png b/kallithea/public/images/icons/printer.png rename from rhodecode/public/images/icons/printer.png rename to kallithea/public/images/icons/printer.png diff --git a/rhodecode/public/images/icons/printer_add.png b/kallithea/public/images/icons/printer_add.png rename from rhodecode/public/images/icons/printer_add.png rename to kallithea/public/images/icons/printer_add.png diff --git a/rhodecode/public/images/icons/printer_delete.png b/kallithea/public/images/icons/printer_delete.png rename from rhodecode/public/images/icons/printer_delete.png rename to kallithea/public/images/icons/printer_delete.png diff --git a/rhodecode/public/images/icons/printer_empty.png b/kallithea/public/images/icons/printer_empty.png rename from rhodecode/public/images/icons/printer_empty.png rename to kallithea/public/images/icons/printer_empty.png diff --git a/rhodecode/public/images/icons/printer_error.png b/kallithea/public/images/icons/printer_error.png rename from rhodecode/public/images/icons/printer_error.png rename to kallithea/public/images/icons/printer_error.png diff --git a/rhodecode/public/images/icons/private_repo.png b/kallithea/public/images/icons/private_repo.png rename from rhodecode/public/images/icons/private_repo.png rename to kallithea/public/images/icons/private_repo.png diff --git a/rhodecode/public/images/icons/public_repo.png b/kallithea/public/images/icons/public_repo.png rename from rhodecode/public/images/icons/public_repo.png rename to kallithea/public/images/icons/public_repo.png diff --git a/rhodecode/public/images/icons/rainbow.png b/kallithea/public/images/icons/rainbow.png rename from rhodecode/public/images/icons/rainbow.png rename to kallithea/public/images/icons/rainbow.png diff --git a/rhodecode/public/images/icons/report.png b/kallithea/public/images/icons/report.png rename from rhodecode/public/images/icons/report.png rename to kallithea/public/images/icons/report.png diff --git a/rhodecode/public/images/icons/report_add.png b/kallithea/public/images/icons/report_add.png rename from rhodecode/public/images/icons/report_add.png rename to kallithea/public/images/icons/report_add.png diff --git a/rhodecode/public/images/icons/report_delete.png b/kallithea/public/images/icons/report_delete.png rename from rhodecode/public/images/icons/report_delete.png rename to kallithea/public/images/icons/report_delete.png diff --git a/rhodecode/public/images/icons/report_disk.png b/kallithea/public/images/icons/report_disk.png rename from rhodecode/public/images/icons/report_disk.png rename to kallithea/public/images/icons/report_disk.png diff --git a/rhodecode/public/images/icons/report_edit.png b/kallithea/public/images/icons/report_edit.png rename from rhodecode/public/images/icons/report_edit.png rename to kallithea/public/images/icons/report_edit.png diff --git a/rhodecode/public/images/icons/report_go.png b/kallithea/public/images/icons/report_go.png rename from rhodecode/public/images/icons/report_go.png rename to kallithea/public/images/icons/report_go.png diff --git a/rhodecode/public/images/icons/report_key.png b/kallithea/public/images/icons/report_key.png rename from rhodecode/public/images/icons/report_key.png rename to kallithea/public/images/icons/report_key.png diff --git a/rhodecode/public/images/icons/report_link.png b/kallithea/public/images/icons/report_link.png rename from rhodecode/public/images/icons/report_link.png rename to kallithea/public/images/icons/report_link.png diff --git a/rhodecode/public/images/icons/report_magnify.png b/kallithea/public/images/icons/report_magnify.png rename from rhodecode/public/images/icons/report_magnify.png rename to kallithea/public/images/icons/report_magnify.png diff --git a/rhodecode/public/images/icons/report_picture.png b/kallithea/public/images/icons/report_picture.png rename from rhodecode/public/images/icons/report_picture.png rename to kallithea/public/images/icons/report_picture.png diff --git a/rhodecode/public/images/icons/report_user.png b/kallithea/public/images/icons/report_user.png rename from rhodecode/public/images/icons/report_user.png rename to kallithea/public/images/icons/report_user.png diff --git a/rhodecode/public/images/icons/report_word.png b/kallithea/public/images/icons/report_word.png rename from rhodecode/public/images/icons/report_word.png rename to kallithea/public/images/icons/report_word.png diff --git a/rhodecode/public/images/icons/resultset_first.png b/kallithea/public/images/icons/resultset_first.png rename from rhodecode/public/images/icons/resultset_first.png rename to kallithea/public/images/icons/resultset_first.png diff --git a/rhodecode/public/images/icons/resultset_last.png b/kallithea/public/images/icons/resultset_last.png rename from rhodecode/public/images/icons/resultset_last.png rename to kallithea/public/images/icons/resultset_last.png diff --git a/rhodecode/public/images/icons/resultset_next.png b/kallithea/public/images/icons/resultset_next.png rename from rhodecode/public/images/icons/resultset_next.png rename to kallithea/public/images/icons/resultset_next.png diff --git a/rhodecode/public/images/icons/resultset_previous.png b/kallithea/public/images/icons/resultset_previous.png rename from rhodecode/public/images/icons/resultset_previous.png rename to kallithea/public/images/icons/resultset_previous.png diff --git a/rhodecode/public/images/icons/right_16.png b/kallithea/public/images/icons/right_16.png rename from rhodecode/public/images/icons/right_16.png rename to kallithea/public/images/icons/right_16.png diff --git a/rhodecode/public/images/icons/rosette.png b/kallithea/public/images/icons/rosette.png rename from rhodecode/public/images/icons/rosette.png rename to kallithea/public/images/icons/rosette.png diff --git a/rhodecode/public/images/icons/rss.png b/kallithea/public/images/icons/rss.png rename from rhodecode/public/images/icons/rss.png rename to kallithea/public/images/icons/rss.png diff --git a/rhodecode/public/images/icons/rss_16.png b/kallithea/public/images/icons/rss_16.png rename from rhodecode/public/images/icons/rss_16.png rename to kallithea/public/images/icons/rss_16.png diff --git a/rhodecode/public/images/icons/rss_add.png b/kallithea/public/images/icons/rss_add.png rename from rhodecode/public/images/icons/rss_add.png rename to kallithea/public/images/icons/rss_add.png diff --git a/rhodecode/public/images/icons/rss_delete.png b/kallithea/public/images/icons/rss_delete.png rename from rhodecode/public/images/icons/rss_delete.png rename to kallithea/public/images/icons/rss_delete.png diff --git a/rhodecode/public/images/icons/rss_go.png b/kallithea/public/images/icons/rss_go.png rename from rhodecode/public/images/icons/rss_go.png rename to kallithea/public/images/icons/rss_go.png diff --git a/rhodecode/public/images/icons/rss_valid.png b/kallithea/public/images/icons/rss_valid.png rename from rhodecode/public/images/icons/rss_valid.png rename to kallithea/public/images/icons/rss_valid.png diff --git a/rhodecode/public/images/icons/ruby.png b/kallithea/public/images/icons/ruby.png rename from rhodecode/public/images/icons/ruby.png rename to kallithea/public/images/icons/ruby.png diff --git a/rhodecode/public/images/icons/ruby_add.png b/kallithea/public/images/icons/ruby_add.png rename from rhodecode/public/images/icons/ruby_add.png rename to kallithea/public/images/icons/ruby_add.png diff --git a/rhodecode/public/images/icons/ruby_delete.png b/kallithea/public/images/icons/ruby_delete.png rename from rhodecode/public/images/icons/ruby_delete.png rename to kallithea/public/images/icons/ruby_delete.png diff --git a/rhodecode/public/images/icons/ruby_gear.png b/kallithea/public/images/icons/ruby_gear.png rename from rhodecode/public/images/icons/ruby_gear.png rename to kallithea/public/images/icons/ruby_gear.png diff --git a/rhodecode/public/images/icons/ruby_get.png b/kallithea/public/images/icons/ruby_get.png rename from rhodecode/public/images/icons/ruby_get.png rename to kallithea/public/images/icons/ruby_get.png diff --git a/rhodecode/public/images/icons/ruby_go.png b/kallithea/public/images/icons/ruby_go.png rename from rhodecode/public/images/icons/ruby_go.png rename to kallithea/public/images/icons/ruby_go.png diff --git a/rhodecode/public/images/icons/ruby_key.png b/kallithea/public/images/icons/ruby_key.png rename from rhodecode/public/images/icons/ruby_key.png rename to kallithea/public/images/icons/ruby_key.png diff --git a/rhodecode/public/images/icons/ruby_link.png b/kallithea/public/images/icons/ruby_link.png rename from rhodecode/public/images/icons/ruby_link.png rename to kallithea/public/images/icons/ruby_link.png diff --git a/rhodecode/public/images/icons/ruby_put.png b/kallithea/public/images/icons/ruby_put.png rename from rhodecode/public/images/icons/ruby_put.png rename to kallithea/public/images/icons/ruby_put.png diff --git a/rhodecode/public/images/icons/save_16.png b/kallithea/public/images/icons/save_16.png rename from rhodecode/public/images/icons/save_16.png rename to kallithea/public/images/icons/save_16.png diff --git a/rhodecode/public/images/icons/script.png b/kallithea/public/images/icons/script.png rename from rhodecode/public/images/icons/script.png rename to kallithea/public/images/icons/script.png diff --git a/rhodecode/public/images/icons/script_add.png b/kallithea/public/images/icons/script_add.png rename from rhodecode/public/images/icons/script_add.png rename to kallithea/public/images/icons/script_add.png diff --git a/rhodecode/public/images/icons/script_code.png b/kallithea/public/images/icons/script_code.png rename from rhodecode/public/images/icons/script_code.png rename to kallithea/public/images/icons/script_code.png diff --git a/rhodecode/public/images/icons/script_code_red.png b/kallithea/public/images/icons/script_code_red.png rename from rhodecode/public/images/icons/script_code_red.png rename to kallithea/public/images/icons/script_code_red.png diff --git a/rhodecode/public/images/icons/script_delete.png b/kallithea/public/images/icons/script_delete.png rename from rhodecode/public/images/icons/script_delete.png rename to kallithea/public/images/icons/script_delete.png diff --git a/rhodecode/public/images/icons/script_edit.png b/kallithea/public/images/icons/script_edit.png rename from rhodecode/public/images/icons/script_edit.png rename to kallithea/public/images/icons/script_edit.png diff --git a/rhodecode/public/images/icons/script_error.png b/kallithea/public/images/icons/script_error.png rename from rhodecode/public/images/icons/script_error.png rename to kallithea/public/images/icons/script_error.png diff --git a/rhodecode/public/images/icons/script_gear.png b/kallithea/public/images/icons/script_gear.png rename from rhodecode/public/images/icons/script_gear.png rename to kallithea/public/images/icons/script_gear.png diff --git a/rhodecode/public/images/icons/script_go.png b/kallithea/public/images/icons/script_go.png rename from rhodecode/public/images/icons/script_go.png rename to kallithea/public/images/icons/script_go.png diff --git a/rhodecode/public/images/icons/script_key.png b/kallithea/public/images/icons/script_key.png rename from rhodecode/public/images/icons/script_key.png rename to kallithea/public/images/icons/script_key.png diff --git a/rhodecode/public/images/icons/script_lightning.png b/kallithea/public/images/icons/script_lightning.png rename from rhodecode/public/images/icons/script_lightning.png rename to kallithea/public/images/icons/script_lightning.png diff --git a/rhodecode/public/images/icons/script_link.png b/kallithea/public/images/icons/script_link.png rename from rhodecode/public/images/icons/script_link.png rename to kallithea/public/images/icons/script_link.png diff --git a/rhodecode/public/images/icons/script_palette.png b/kallithea/public/images/icons/script_palette.png rename from rhodecode/public/images/icons/script_palette.png rename to kallithea/public/images/icons/script_palette.png diff --git a/rhodecode/public/images/icons/script_save.png b/kallithea/public/images/icons/script_save.png rename from rhodecode/public/images/icons/script_save.png rename to kallithea/public/images/icons/script_save.png diff --git a/rhodecode/public/images/icons/search_16.png b/kallithea/public/images/icons/search_16.png rename from rhodecode/public/images/icons/search_16.png rename to kallithea/public/images/icons/search_16.png diff --git a/rhodecode/public/images/icons/server.png b/kallithea/public/images/icons/server.png rename from rhodecode/public/images/icons/server.png rename to kallithea/public/images/icons/server.png diff --git a/rhodecode/public/images/icons/server_add.png b/kallithea/public/images/icons/server_add.png rename from rhodecode/public/images/icons/server_add.png rename to kallithea/public/images/icons/server_add.png diff --git a/rhodecode/public/images/icons/server_chart.png b/kallithea/public/images/icons/server_chart.png rename from rhodecode/public/images/icons/server_chart.png rename to kallithea/public/images/icons/server_chart.png diff --git a/rhodecode/public/images/icons/server_compressed.png b/kallithea/public/images/icons/server_compressed.png rename from rhodecode/public/images/icons/server_compressed.png rename to kallithea/public/images/icons/server_compressed.png diff --git a/rhodecode/public/images/icons/server_connect.png b/kallithea/public/images/icons/server_connect.png rename from rhodecode/public/images/icons/server_connect.png rename to kallithea/public/images/icons/server_connect.png diff --git a/rhodecode/public/images/icons/server_database.png b/kallithea/public/images/icons/server_database.png rename from rhodecode/public/images/icons/server_database.png rename to kallithea/public/images/icons/server_database.png diff --git a/rhodecode/public/images/icons/server_delete.png b/kallithea/public/images/icons/server_delete.png rename from rhodecode/public/images/icons/server_delete.png rename to kallithea/public/images/icons/server_delete.png diff --git a/rhodecode/public/images/icons/server_edit.png b/kallithea/public/images/icons/server_edit.png rename from rhodecode/public/images/icons/server_edit.png rename to kallithea/public/images/icons/server_edit.png diff --git a/rhodecode/public/images/icons/server_error.png b/kallithea/public/images/icons/server_error.png rename from rhodecode/public/images/icons/server_error.png rename to kallithea/public/images/icons/server_error.png diff --git a/rhodecode/public/images/icons/server_go.png b/kallithea/public/images/icons/server_go.png rename from rhodecode/public/images/icons/server_go.png rename to kallithea/public/images/icons/server_go.png diff --git a/rhodecode/public/images/icons/server_key.png b/kallithea/public/images/icons/server_key.png rename from rhodecode/public/images/icons/server_key.png rename to kallithea/public/images/icons/server_key.png diff --git a/rhodecode/public/images/icons/server_lightning.png b/kallithea/public/images/icons/server_lightning.png rename from rhodecode/public/images/icons/server_lightning.png rename to kallithea/public/images/icons/server_lightning.png diff --git a/rhodecode/public/images/icons/server_link.png b/kallithea/public/images/icons/server_link.png rename from rhodecode/public/images/icons/server_link.png rename to kallithea/public/images/icons/server_link.png diff --git a/rhodecode/public/images/icons/server_uncompressed.png b/kallithea/public/images/icons/server_uncompressed.png rename from rhodecode/public/images/icons/server_uncompressed.png rename to kallithea/public/images/icons/server_uncompressed.png diff --git a/rhodecode/public/images/icons/shading.png b/kallithea/public/images/icons/shading.png rename from rhodecode/public/images/icons/shading.png rename to kallithea/public/images/icons/shading.png diff --git a/rhodecode/public/images/icons/shape_align_bottom.png b/kallithea/public/images/icons/shape_align_bottom.png rename from rhodecode/public/images/icons/shape_align_bottom.png rename to kallithea/public/images/icons/shape_align_bottom.png diff --git a/rhodecode/public/images/icons/shape_align_center.png b/kallithea/public/images/icons/shape_align_center.png rename from rhodecode/public/images/icons/shape_align_center.png rename to kallithea/public/images/icons/shape_align_center.png diff --git a/rhodecode/public/images/icons/shape_align_left.png b/kallithea/public/images/icons/shape_align_left.png rename from rhodecode/public/images/icons/shape_align_left.png rename to kallithea/public/images/icons/shape_align_left.png diff --git a/rhodecode/public/images/icons/shape_align_middle.png b/kallithea/public/images/icons/shape_align_middle.png rename from rhodecode/public/images/icons/shape_align_middle.png rename to kallithea/public/images/icons/shape_align_middle.png diff --git a/rhodecode/public/images/icons/shape_align_right.png b/kallithea/public/images/icons/shape_align_right.png rename from rhodecode/public/images/icons/shape_align_right.png rename to kallithea/public/images/icons/shape_align_right.png diff --git a/rhodecode/public/images/icons/shape_align_top.png b/kallithea/public/images/icons/shape_align_top.png rename from rhodecode/public/images/icons/shape_align_top.png rename to kallithea/public/images/icons/shape_align_top.png diff --git a/rhodecode/public/images/icons/shape_flip_horizontal.png b/kallithea/public/images/icons/shape_flip_horizontal.png rename from rhodecode/public/images/icons/shape_flip_horizontal.png rename to kallithea/public/images/icons/shape_flip_horizontal.png diff --git a/rhodecode/public/images/icons/shape_flip_vertical.png b/kallithea/public/images/icons/shape_flip_vertical.png rename from rhodecode/public/images/icons/shape_flip_vertical.png rename to kallithea/public/images/icons/shape_flip_vertical.png diff --git a/rhodecode/public/images/icons/shape_group.png b/kallithea/public/images/icons/shape_group.png rename from rhodecode/public/images/icons/shape_group.png rename to kallithea/public/images/icons/shape_group.png diff --git a/rhodecode/public/images/icons/shape_handles.png b/kallithea/public/images/icons/shape_handles.png rename from rhodecode/public/images/icons/shape_handles.png rename to kallithea/public/images/icons/shape_handles.png diff --git a/rhodecode/public/images/icons/shape_move_back.png b/kallithea/public/images/icons/shape_move_back.png rename from rhodecode/public/images/icons/shape_move_back.png rename to kallithea/public/images/icons/shape_move_back.png diff --git a/rhodecode/public/images/icons/shape_move_backwards.png b/kallithea/public/images/icons/shape_move_backwards.png rename from rhodecode/public/images/icons/shape_move_backwards.png rename to kallithea/public/images/icons/shape_move_backwards.png diff --git a/rhodecode/public/images/icons/shape_move_forwards.png b/kallithea/public/images/icons/shape_move_forwards.png rename from rhodecode/public/images/icons/shape_move_forwards.png rename to kallithea/public/images/icons/shape_move_forwards.png diff --git a/rhodecode/public/images/icons/shape_move_front.png b/kallithea/public/images/icons/shape_move_front.png rename from rhodecode/public/images/icons/shape_move_front.png rename to kallithea/public/images/icons/shape_move_front.png diff --git a/rhodecode/public/images/icons/shape_rotate_anticlockwise.png b/kallithea/public/images/icons/shape_rotate_anticlockwise.png rename from rhodecode/public/images/icons/shape_rotate_anticlockwise.png rename to kallithea/public/images/icons/shape_rotate_anticlockwise.png diff --git a/rhodecode/public/images/icons/shape_rotate_clockwise.png b/kallithea/public/images/icons/shape_rotate_clockwise.png rename from rhodecode/public/images/icons/shape_rotate_clockwise.png rename to kallithea/public/images/icons/shape_rotate_clockwise.png diff --git a/rhodecode/public/images/icons/shape_square.png b/kallithea/public/images/icons/shape_square.png rename from rhodecode/public/images/icons/shape_square.png rename to kallithea/public/images/icons/shape_square.png diff --git a/rhodecode/public/images/icons/shape_square_add.png b/kallithea/public/images/icons/shape_square_add.png rename from rhodecode/public/images/icons/shape_square_add.png rename to kallithea/public/images/icons/shape_square_add.png diff --git a/rhodecode/public/images/icons/shape_square_delete.png b/kallithea/public/images/icons/shape_square_delete.png rename from rhodecode/public/images/icons/shape_square_delete.png rename to kallithea/public/images/icons/shape_square_delete.png diff --git a/rhodecode/public/images/icons/shape_square_edit.png b/kallithea/public/images/icons/shape_square_edit.png rename from rhodecode/public/images/icons/shape_square_edit.png rename to kallithea/public/images/icons/shape_square_edit.png diff --git a/rhodecode/public/images/icons/shape_square_error.png b/kallithea/public/images/icons/shape_square_error.png rename from rhodecode/public/images/icons/shape_square_error.png rename to kallithea/public/images/icons/shape_square_error.png diff --git a/rhodecode/public/images/icons/shape_square_go.png b/kallithea/public/images/icons/shape_square_go.png rename from rhodecode/public/images/icons/shape_square_go.png rename to kallithea/public/images/icons/shape_square_go.png diff --git a/rhodecode/public/images/icons/shape_square_key.png b/kallithea/public/images/icons/shape_square_key.png rename from rhodecode/public/images/icons/shape_square_key.png rename to kallithea/public/images/icons/shape_square_key.png diff --git a/rhodecode/public/images/icons/shape_square_link.png b/kallithea/public/images/icons/shape_square_link.png rename from rhodecode/public/images/icons/shape_square_link.png rename to kallithea/public/images/icons/shape_square_link.png diff --git a/rhodecode/public/images/icons/shape_ungroup.png b/kallithea/public/images/icons/shape_ungroup.png rename from rhodecode/public/images/icons/shape_ungroup.png rename to kallithea/public/images/icons/shape_ungroup.png diff --git a/rhodecode/public/images/icons/shield.png b/kallithea/public/images/icons/shield.png rename from rhodecode/public/images/icons/shield.png rename to kallithea/public/images/icons/shield.png diff --git a/rhodecode/public/images/icons/shield_16.png b/kallithea/public/images/icons/shield_16.png rename from rhodecode/public/images/icons/shield_16.png rename to kallithea/public/images/icons/shield_16.png diff --git a/rhodecode/public/images/icons/shield_add.png b/kallithea/public/images/icons/shield_add.png rename from rhodecode/public/images/icons/shield_add.png rename to kallithea/public/images/icons/shield_add.png diff --git a/rhodecode/public/images/icons/shield_delete.png b/kallithea/public/images/icons/shield_delete.png rename from rhodecode/public/images/icons/shield_delete.png rename to kallithea/public/images/icons/shield_delete.png diff --git a/rhodecode/public/images/icons/shield_go.png b/kallithea/public/images/icons/shield_go.png rename from rhodecode/public/images/icons/shield_go.png rename to kallithea/public/images/icons/shield_go.png diff --git a/rhodecode/public/images/icons/sitemap.png b/kallithea/public/images/icons/sitemap.png rename from rhodecode/public/images/icons/sitemap.png rename to kallithea/public/images/icons/sitemap.png diff --git a/rhodecode/public/images/icons/sitemap_color.png b/kallithea/public/images/icons/sitemap_color.png rename from rhodecode/public/images/icons/sitemap_color.png rename to kallithea/public/images/icons/sitemap_color.png diff --git a/rhodecode/public/images/icons/sound.png b/kallithea/public/images/icons/sound.png rename from rhodecode/public/images/icons/sound.png rename to kallithea/public/images/icons/sound.png diff --git a/rhodecode/public/images/icons/sound_add.png b/kallithea/public/images/icons/sound_add.png rename from rhodecode/public/images/icons/sound_add.png rename to kallithea/public/images/icons/sound_add.png diff --git a/rhodecode/public/images/icons/sound_delete.png b/kallithea/public/images/icons/sound_delete.png rename from rhodecode/public/images/icons/sound_delete.png rename to kallithea/public/images/icons/sound_delete.png diff --git a/rhodecode/public/images/icons/sound_low.png b/kallithea/public/images/icons/sound_low.png rename from rhodecode/public/images/icons/sound_low.png rename to kallithea/public/images/icons/sound_low.png diff --git a/rhodecode/public/images/icons/sound_mute.png b/kallithea/public/images/icons/sound_mute.png rename from rhodecode/public/images/icons/sound_mute.png rename to kallithea/public/images/icons/sound_mute.png diff --git a/rhodecode/public/images/icons/sound_none.png b/kallithea/public/images/icons/sound_none.png rename from rhodecode/public/images/icons/sound_none.png rename to kallithea/public/images/icons/sound_none.png diff --git a/rhodecode/public/images/icons/spellcheck.png b/kallithea/public/images/icons/spellcheck.png rename from rhodecode/public/images/icons/spellcheck.png rename to kallithea/public/images/icons/spellcheck.png diff --git a/rhodecode/public/images/icons/sport_8ball.png b/kallithea/public/images/icons/sport_8ball.png rename from rhodecode/public/images/icons/sport_8ball.png rename to kallithea/public/images/icons/sport_8ball.png diff --git a/rhodecode/public/images/icons/sport_basketball.png b/kallithea/public/images/icons/sport_basketball.png rename from rhodecode/public/images/icons/sport_basketball.png rename to kallithea/public/images/icons/sport_basketball.png diff --git a/rhodecode/public/images/icons/sport_football.png b/kallithea/public/images/icons/sport_football.png rename from rhodecode/public/images/icons/sport_football.png rename to kallithea/public/images/icons/sport_football.png diff --git a/rhodecode/public/images/icons/sport_golf.png b/kallithea/public/images/icons/sport_golf.png rename from rhodecode/public/images/icons/sport_golf.png rename to kallithea/public/images/icons/sport_golf.png diff --git a/rhodecode/public/images/icons/sport_raquet.png b/kallithea/public/images/icons/sport_raquet.png rename from rhodecode/public/images/icons/sport_raquet.png rename to kallithea/public/images/icons/sport_raquet.png diff --git a/rhodecode/public/images/icons/sport_shuttlecock.png b/kallithea/public/images/icons/sport_shuttlecock.png rename from rhodecode/public/images/icons/sport_shuttlecock.png rename to kallithea/public/images/icons/sport_shuttlecock.png diff --git a/rhodecode/public/images/icons/sport_soccer.png b/kallithea/public/images/icons/sport_soccer.png rename from rhodecode/public/images/icons/sport_soccer.png rename to kallithea/public/images/icons/sport_soccer.png diff --git a/rhodecode/public/images/icons/sport_tennis.png b/kallithea/public/images/icons/sport_tennis.png rename from rhodecode/public/images/icons/sport_tennis.png rename to kallithea/public/images/icons/sport_tennis.png diff --git a/rhodecode/public/images/icons/star.png b/kallithea/public/images/icons/star.png rename from rhodecode/public/images/icons/star.png rename to kallithea/public/images/icons/star.png diff --git a/rhodecode/public/images/icons/statistics_16.png b/kallithea/public/images/icons/statistics_16.png rename from rhodecode/public/images/icons/statistics_16.png rename to kallithea/public/images/icons/statistics_16.png diff --git a/rhodecode/public/images/icons/status_away.png b/kallithea/public/images/icons/status_away.png rename from rhodecode/public/images/icons/status_away.png rename to kallithea/public/images/icons/status_away.png diff --git a/rhodecode/public/images/icons/status_busy.png b/kallithea/public/images/icons/status_busy.png rename from rhodecode/public/images/icons/status_busy.png rename to kallithea/public/images/icons/status_busy.png diff --git a/rhodecode/public/images/icons/status_offline.png b/kallithea/public/images/icons/status_offline.png rename from rhodecode/public/images/icons/status_offline.png rename to kallithea/public/images/icons/status_offline.png diff --git a/rhodecode/public/images/icons/status_online.png b/kallithea/public/images/icons/status_online.png rename from rhodecode/public/images/icons/status_online.png rename to kallithea/public/images/icons/status_online.png diff --git a/rhodecode/public/images/icons/stop.png b/kallithea/public/images/icons/stop.png rename from rhodecode/public/images/icons/stop.png rename to kallithea/public/images/icons/stop.png diff --git a/rhodecode/public/images/icons/stop_16.png b/kallithea/public/images/icons/stop_16.png rename from rhodecode/public/images/icons/stop_16.png rename to kallithea/public/images/icons/stop_16.png diff --git a/rhodecode/public/images/icons/style.png b/kallithea/public/images/icons/style.png rename from rhodecode/public/images/icons/style.png rename to kallithea/public/images/icons/style.png diff --git a/rhodecode/public/images/icons/style_add.png b/kallithea/public/images/icons/style_add.png rename from rhodecode/public/images/icons/style_add.png rename to kallithea/public/images/icons/style_add.png diff --git a/rhodecode/public/images/icons/style_delete.png b/kallithea/public/images/icons/style_delete.png rename from rhodecode/public/images/icons/style_delete.png rename to kallithea/public/images/icons/style_delete.png diff --git a/rhodecode/public/images/icons/style_edit.png b/kallithea/public/images/icons/style_edit.png rename from rhodecode/public/images/icons/style_edit.png rename to kallithea/public/images/icons/style_edit.png diff --git a/rhodecode/public/images/icons/style_go.png b/kallithea/public/images/icons/style_go.png rename from rhodecode/public/images/icons/style_go.png rename to kallithea/public/images/icons/style_go.png diff --git a/rhodecode/public/images/icons/success_msg.png b/kallithea/public/images/icons/success_msg.png rename from rhodecode/public/images/icons/success_msg.png rename to kallithea/public/images/icons/success_msg.png diff --git a/rhodecode/public/images/icons/sum.png b/kallithea/public/images/icons/sum.png rename from rhodecode/public/images/icons/sum.png rename to kallithea/public/images/icons/sum.png diff --git a/rhodecode/public/images/icons/tab.png b/kallithea/public/images/icons/tab.png rename from rhodecode/public/images/icons/tab.png rename to kallithea/public/images/icons/tab.png diff --git a/rhodecode/public/images/icons/tab_add.png b/kallithea/public/images/icons/tab_add.png rename from rhodecode/public/images/icons/tab_add.png rename to kallithea/public/images/icons/tab_add.png diff --git a/rhodecode/public/images/icons/tab_delete.png b/kallithea/public/images/icons/tab_delete.png rename from rhodecode/public/images/icons/tab_delete.png rename to kallithea/public/images/icons/tab_delete.png diff --git a/rhodecode/public/images/icons/tab_edit.png b/kallithea/public/images/icons/tab_edit.png rename from rhodecode/public/images/icons/tab_edit.png rename to kallithea/public/images/icons/tab_edit.png diff --git a/rhodecode/public/images/icons/tab_go.png b/kallithea/public/images/icons/tab_go.png rename from rhodecode/public/images/icons/tab_go.png rename to kallithea/public/images/icons/tab_go.png diff --git a/rhodecode/public/images/icons/table.png b/kallithea/public/images/icons/table.png rename from rhodecode/public/images/icons/table.png rename to kallithea/public/images/icons/table.png diff --git a/rhodecode/public/images/icons/table_add.png b/kallithea/public/images/icons/table_add.png rename from rhodecode/public/images/icons/table_add.png rename to kallithea/public/images/icons/table_add.png diff --git a/rhodecode/public/images/icons/table_delete.png b/kallithea/public/images/icons/table_delete.png rename from rhodecode/public/images/icons/table_delete.png rename to kallithea/public/images/icons/table_delete.png diff --git a/rhodecode/public/images/icons/table_edit.png b/kallithea/public/images/icons/table_edit.png rename from rhodecode/public/images/icons/table_edit.png rename to kallithea/public/images/icons/table_edit.png diff --git a/rhodecode/public/images/icons/table_error.png b/kallithea/public/images/icons/table_error.png rename from rhodecode/public/images/icons/table_error.png rename to kallithea/public/images/icons/table_error.png diff --git a/rhodecode/public/images/icons/table_gear.png b/kallithea/public/images/icons/table_gear.png rename from rhodecode/public/images/icons/table_gear.png rename to kallithea/public/images/icons/table_gear.png diff --git a/rhodecode/public/images/icons/table_go.png b/kallithea/public/images/icons/table_go.png rename from rhodecode/public/images/icons/table_go.png rename to kallithea/public/images/icons/table_go.png diff --git a/rhodecode/public/images/icons/table_key.png b/kallithea/public/images/icons/table_key.png rename from rhodecode/public/images/icons/table_key.png rename to kallithea/public/images/icons/table_key.png diff --git a/rhodecode/public/images/icons/table_lightning.png b/kallithea/public/images/icons/table_lightning.png rename from rhodecode/public/images/icons/table_lightning.png rename to kallithea/public/images/icons/table_lightning.png diff --git a/rhodecode/public/images/icons/table_link.png b/kallithea/public/images/icons/table_link.png rename from rhodecode/public/images/icons/table_link.png rename to kallithea/public/images/icons/table_link.png diff --git a/rhodecode/public/images/icons/table_multiple.png b/kallithea/public/images/icons/table_multiple.png rename from rhodecode/public/images/icons/table_multiple.png rename to kallithea/public/images/icons/table_multiple.png diff --git a/rhodecode/public/images/icons/table_refresh.png b/kallithea/public/images/icons/table_refresh.png rename from rhodecode/public/images/icons/table_refresh.png rename to kallithea/public/images/icons/table_refresh.png diff --git a/rhodecode/public/images/icons/table_relationship.png b/kallithea/public/images/icons/table_relationship.png rename from rhodecode/public/images/icons/table_relationship.png rename to kallithea/public/images/icons/table_relationship.png diff --git a/rhodecode/public/images/icons/table_row_delete.png b/kallithea/public/images/icons/table_row_delete.png rename from rhodecode/public/images/icons/table_row_delete.png rename to kallithea/public/images/icons/table_row_delete.png diff --git a/rhodecode/public/images/icons/table_row_insert.png b/kallithea/public/images/icons/table_row_insert.png rename from rhodecode/public/images/icons/table_row_insert.png rename to kallithea/public/images/icons/table_row_insert.png diff --git a/rhodecode/public/images/icons/table_save.png b/kallithea/public/images/icons/table_save.png rename from rhodecode/public/images/icons/table_save.png rename to kallithea/public/images/icons/table_save.png diff --git a/rhodecode/public/images/icons/table_sort.png b/kallithea/public/images/icons/table_sort.png rename from rhodecode/public/images/icons/table_sort.png rename to kallithea/public/images/icons/table_sort.png diff --git a/rhodecode/public/images/icons/tag.png b/kallithea/public/images/icons/tag.png rename from rhodecode/public/images/icons/tag.png rename to kallithea/public/images/icons/tag.png diff --git a/rhodecode/public/images/icons/tag_blue.png b/kallithea/public/images/icons/tag_blue.png rename from rhodecode/public/images/icons/tag_blue.png rename to kallithea/public/images/icons/tag_blue.png diff --git a/rhodecode/public/images/icons/tag_blue_add.png b/kallithea/public/images/icons/tag_blue_add.png rename from rhodecode/public/images/icons/tag_blue_add.png rename to kallithea/public/images/icons/tag_blue_add.png diff --git a/rhodecode/public/images/icons/tag_blue_delete.png b/kallithea/public/images/icons/tag_blue_delete.png rename from rhodecode/public/images/icons/tag_blue_delete.png rename to kallithea/public/images/icons/tag_blue_delete.png diff --git a/rhodecode/public/images/icons/tag_blue_edit.png b/kallithea/public/images/icons/tag_blue_edit.png rename from rhodecode/public/images/icons/tag_blue_edit.png rename to kallithea/public/images/icons/tag_blue_edit.png diff --git a/rhodecode/public/images/icons/tag_green.png b/kallithea/public/images/icons/tag_green.png rename from rhodecode/public/images/icons/tag_green.png rename to kallithea/public/images/icons/tag_green.png diff --git a/rhodecode/public/images/icons/tag_orange.png b/kallithea/public/images/icons/tag_orange.png rename from rhodecode/public/images/icons/tag_orange.png rename to kallithea/public/images/icons/tag_orange.png diff --git a/rhodecode/public/images/icons/tag_pink.png b/kallithea/public/images/icons/tag_pink.png rename from rhodecode/public/images/icons/tag_pink.png rename to kallithea/public/images/icons/tag_pink.png diff --git a/rhodecode/public/images/icons/tag_purple.png b/kallithea/public/images/icons/tag_purple.png rename from rhodecode/public/images/icons/tag_purple.png rename to kallithea/public/images/icons/tag_purple.png diff --git a/rhodecode/public/images/icons/tag_red.png b/kallithea/public/images/icons/tag_red.png rename from rhodecode/public/images/icons/tag_red.png rename to kallithea/public/images/icons/tag_red.png diff --git a/rhodecode/public/images/icons/tag_yellow.png b/kallithea/public/images/icons/tag_yellow.png rename from rhodecode/public/images/icons/tag_yellow.png rename to kallithea/public/images/icons/tag_yellow.png diff --git a/rhodecode/public/images/icons/telephone.png b/kallithea/public/images/icons/telephone.png rename from rhodecode/public/images/icons/telephone.png rename to kallithea/public/images/icons/telephone.png diff --git a/rhodecode/public/images/icons/telephone_add.png b/kallithea/public/images/icons/telephone_add.png rename from rhodecode/public/images/icons/telephone_add.png rename to kallithea/public/images/icons/telephone_add.png diff --git a/rhodecode/public/images/icons/telephone_delete.png b/kallithea/public/images/icons/telephone_delete.png rename from rhodecode/public/images/icons/telephone_delete.png rename to kallithea/public/images/icons/telephone_delete.png diff --git a/rhodecode/public/images/icons/telephone_edit.png b/kallithea/public/images/icons/telephone_edit.png rename from rhodecode/public/images/icons/telephone_edit.png rename to kallithea/public/images/icons/telephone_edit.png diff --git a/rhodecode/public/images/icons/telephone_error.png b/kallithea/public/images/icons/telephone_error.png rename from rhodecode/public/images/icons/telephone_error.png rename to kallithea/public/images/icons/telephone_error.png diff --git a/rhodecode/public/images/icons/telephone_go.png b/kallithea/public/images/icons/telephone_go.png rename from rhodecode/public/images/icons/telephone_go.png rename to kallithea/public/images/icons/telephone_go.png diff --git a/rhodecode/public/images/icons/telephone_key.png b/kallithea/public/images/icons/telephone_key.png rename from rhodecode/public/images/icons/telephone_key.png rename to kallithea/public/images/icons/telephone_key.png diff --git a/rhodecode/public/images/icons/telephone_link.png b/kallithea/public/images/icons/telephone_link.png rename from rhodecode/public/images/icons/telephone_link.png rename to kallithea/public/images/icons/telephone_link.png diff --git a/rhodecode/public/images/icons/television.png b/kallithea/public/images/icons/television.png rename from rhodecode/public/images/icons/television.png rename to kallithea/public/images/icons/television.png diff --git a/rhodecode/public/images/icons/television_add.png b/kallithea/public/images/icons/television_add.png rename from rhodecode/public/images/icons/television_add.png rename to kallithea/public/images/icons/television_add.png diff --git a/rhodecode/public/images/icons/television_delete.png b/kallithea/public/images/icons/television_delete.png rename from rhodecode/public/images/icons/television_delete.png rename to kallithea/public/images/icons/television_delete.png diff --git a/rhodecode/public/images/icons/text_align_center.png b/kallithea/public/images/icons/text_align_center.png rename from rhodecode/public/images/icons/text_align_center.png rename to kallithea/public/images/icons/text_align_center.png diff --git a/rhodecode/public/images/icons/text_align_justify.png b/kallithea/public/images/icons/text_align_justify.png rename from rhodecode/public/images/icons/text_align_justify.png rename to kallithea/public/images/icons/text_align_justify.png diff --git a/rhodecode/public/images/icons/text_align_left.png b/kallithea/public/images/icons/text_align_left.png rename from rhodecode/public/images/icons/text_align_left.png rename to kallithea/public/images/icons/text_align_left.png diff --git a/rhodecode/public/images/icons/text_align_right.png b/kallithea/public/images/icons/text_align_right.png rename from rhodecode/public/images/icons/text_align_right.png rename to kallithea/public/images/icons/text_align_right.png diff --git a/rhodecode/public/images/icons/text_allcaps.png b/kallithea/public/images/icons/text_allcaps.png rename from rhodecode/public/images/icons/text_allcaps.png rename to kallithea/public/images/icons/text_allcaps.png diff --git a/rhodecode/public/images/icons/text_bold.png b/kallithea/public/images/icons/text_bold.png rename from rhodecode/public/images/icons/text_bold.png rename to kallithea/public/images/icons/text_bold.png diff --git a/rhodecode/public/images/icons/text_columns.png b/kallithea/public/images/icons/text_columns.png rename from rhodecode/public/images/icons/text_columns.png rename to kallithea/public/images/icons/text_columns.png diff --git a/rhodecode/public/images/icons/text_dropcaps.png b/kallithea/public/images/icons/text_dropcaps.png rename from rhodecode/public/images/icons/text_dropcaps.png rename to kallithea/public/images/icons/text_dropcaps.png diff --git a/rhodecode/public/images/icons/text_heading_1.png b/kallithea/public/images/icons/text_heading_1.png rename from rhodecode/public/images/icons/text_heading_1.png rename to kallithea/public/images/icons/text_heading_1.png diff --git a/rhodecode/public/images/icons/text_heading_2.png b/kallithea/public/images/icons/text_heading_2.png rename from rhodecode/public/images/icons/text_heading_2.png rename to kallithea/public/images/icons/text_heading_2.png diff --git a/rhodecode/public/images/icons/text_heading_3.png b/kallithea/public/images/icons/text_heading_3.png rename from rhodecode/public/images/icons/text_heading_3.png rename to kallithea/public/images/icons/text_heading_3.png diff --git a/rhodecode/public/images/icons/text_heading_4.png b/kallithea/public/images/icons/text_heading_4.png rename from rhodecode/public/images/icons/text_heading_4.png rename to kallithea/public/images/icons/text_heading_4.png diff --git a/rhodecode/public/images/icons/text_heading_5.png b/kallithea/public/images/icons/text_heading_5.png rename from rhodecode/public/images/icons/text_heading_5.png rename to kallithea/public/images/icons/text_heading_5.png diff --git a/rhodecode/public/images/icons/text_heading_6.png b/kallithea/public/images/icons/text_heading_6.png rename from rhodecode/public/images/icons/text_heading_6.png rename to kallithea/public/images/icons/text_heading_6.png diff --git a/rhodecode/public/images/icons/text_horizontalrule.png b/kallithea/public/images/icons/text_horizontalrule.png rename from rhodecode/public/images/icons/text_horizontalrule.png rename to kallithea/public/images/icons/text_horizontalrule.png diff --git a/rhodecode/public/images/icons/text_indent.png b/kallithea/public/images/icons/text_indent.png rename from rhodecode/public/images/icons/text_indent.png rename to kallithea/public/images/icons/text_indent.png diff --git a/rhodecode/public/images/icons/text_indent_remove.png b/kallithea/public/images/icons/text_indent_remove.png rename from rhodecode/public/images/icons/text_indent_remove.png rename to kallithea/public/images/icons/text_indent_remove.png diff --git a/rhodecode/public/images/icons/text_italic.png b/kallithea/public/images/icons/text_italic.png rename from rhodecode/public/images/icons/text_italic.png rename to kallithea/public/images/icons/text_italic.png diff --git a/rhodecode/public/images/icons/text_kerning.png b/kallithea/public/images/icons/text_kerning.png rename from rhodecode/public/images/icons/text_kerning.png rename to kallithea/public/images/icons/text_kerning.png diff --git a/rhodecode/public/images/icons/text_letter_omega.png b/kallithea/public/images/icons/text_letter_omega.png rename from rhodecode/public/images/icons/text_letter_omega.png rename to kallithea/public/images/icons/text_letter_omega.png diff --git a/rhodecode/public/images/icons/text_letterspacing.png b/kallithea/public/images/icons/text_letterspacing.png rename from rhodecode/public/images/icons/text_letterspacing.png rename to kallithea/public/images/icons/text_letterspacing.png diff --git a/rhodecode/public/images/icons/text_linespacing.png b/kallithea/public/images/icons/text_linespacing.png rename from rhodecode/public/images/icons/text_linespacing.png rename to kallithea/public/images/icons/text_linespacing.png diff --git a/rhodecode/public/images/icons/text_list_bullets.png b/kallithea/public/images/icons/text_list_bullets.png rename from rhodecode/public/images/icons/text_list_bullets.png rename to kallithea/public/images/icons/text_list_bullets.png diff --git a/rhodecode/public/images/icons/text_list_numbers.png b/kallithea/public/images/icons/text_list_numbers.png rename from rhodecode/public/images/icons/text_list_numbers.png rename to kallithea/public/images/icons/text_list_numbers.png diff --git a/rhodecode/public/images/icons/text_lowercase.png b/kallithea/public/images/icons/text_lowercase.png rename from rhodecode/public/images/icons/text_lowercase.png rename to kallithea/public/images/icons/text_lowercase.png diff --git a/rhodecode/public/images/icons/text_padding_bottom.png b/kallithea/public/images/icons/text_padding_bottom.png rename from rhodecode/public/images/icons/text_padding_bottom.png rename to kallithea/public/images/icons/text_padding_bottom.png diff --git a/rhodecode/public/images/icons/text_padding_left.png b/kallithea/public/images/icons/text_padding_left.png rename from rhodecode/public/images/icons/text_padding_left.png rename to kallithea/public/images/icons/text_padding_left.png diff --git a/rhodecode/public/images/icons/text_padding_right.png b/kallithea/public/images/icons/text_padding_right.png rename from rhodecode/public/images/icons/text_padding_right.png rename to kallithea/public/images/icons/text_padding_right.png diff --git a/rhodecode/public/images/icons/text_padding_top.png b/kallithea/public/images/icons/text_padding_top.png rename from rhodecode/public/images/icons/text_padding_top.png rename to kallithea/public/images/icons/text_padding_top.png diff --git a/rhodecode/public/images/icons/text_replace.png b/kallithea/public/images/icons/text_replace.png rename from rhodecode/public/images/icons/text_replace.png rename to kallithea/public/images/icons/text_replace.png diff --git a/rhodecode/public/images/icons/text_signature.png b/kallithea/public/images/icons/text_signature.png rename from rhodecode/public/images/icons/text_signature.png rename to kallithea/public/images/icons/text_signature.png diff --git a/rhodecode/public/images/icons/text_smallcaps.png b/kallithea/public/images/icons/text_smallcaps.png rename from rhodecode/public/images/icons/text_smallcaps.png rename to kallithea/public/images/icons/text_smallcaps.png diff --git a/rhodecode/public/images/icons/text_strikethrough.png b/kallithea/public/images/icons/text_strikethrough.png rename from rhodecode/public/images/icons/text_strikethrough.png rename to kallithea/public/images/icons/text_strikethrough.png diff --git a/rhodecode/public/images/icons/text_subscript.png b/kallithea/public/images/icons/text_subscript.png rename from rhodecode/public/images/icons/text_subscript.png rename to kallithea/public/images/icons/text_subscript.png diff --git a/rhodecode/public/images/icons/text_superscript.png b/kallithea/public/images/icons/text_superscript.png rename from rhodecode/public/images/icons/text_superscript.png rename to kallithea/public/images/icons/text_superscript.png diff --git a/rhodecode/public/images/icons/text_underline.png b/kallithea/public/images/icons/text_underline.png rename from rhodecode/public/images/icons/text_underline.png rename to kallithea/public/images/icons/text_underline.png diff --git a/rhodecode/public/images/icons/text_uppercase.png b/kallithea/public/images/icons/text_uppercase.png rename from rhodecode/public/images/icons/text_uppercase.png rename to kallithea/public/images/icons/text_uppercase.png diff --git a/rhodecode/public/images/icons/textfield.png b/kallithea/public/images/icons/textfield.png rename from rhodecode/public/images/icons/textfield.png rename to kallithea/public/images/icons/textfield.png diff --git a/rhodecode/public/images/icons/textfield_add.png b/kallithea/public/images/icons/textfield_add.png rename from rhodecode/public/images/icons/textfield_add.png rename to kallithea/public/images/icons/textfield_add.png diff --git a/rhodecode/public/images/icons/textfield_delete.png b/kallithea/public/images/icons/textfield_delete.png rename from rhodecode/public/images/icons/textfield_delete.png rename to kallithea/public/images/icons/textfield_delete.png diff --git a/rhodecode/public/images/icons/textfield_key.png b/kallithea/public/images/icons/textfield_key.png rename from rhodecode/public/images/icons/textfield_key.png rename to kallithea/public/images/icons/textfield_key.png diff --git a/rhodecode/public/images/icons/textfield_rename.png b/kallithea/public/images/icons/textfield_rename.png rename from rhodecode/public/images/icons/textfield_rename.png rename to kallithea/public/images/icons/textfield_rename.png diff --git a/rhodecode/public/images/icons/thumb_down.png b/kallithea/public/images/icons/thumb_down.png rename from rhodecode/public/images/icons/thumb_down.png rename to kallithea/public/images/icons/thumb_down.png diff --git a/rhodecode/public/images/icons/thumb_up.png b/kallithea/public/images/icons/thumb_up.png rename from rhodecode/public/images/icons/thumb_up.png rename to kallithea/public/images/icons/thumb_up.png diff --git a/rhodecode/public/images/icons/tick.png b/kallithea/public/images/icons/tick.png rename from rhodecode/public/images/icons/tick.png rename to kallithea/public/images/icons/tick.png diff --git a/rhodecode/public/images/icons/tick_16.png b/kallithea/public/images/icons/tick_16.png rename from rhodecode/public/images/icons/tick_16.png rename to kallithea/public/images/icons/tick_16.png diff --git a/rhodecode/public/images/icons/time.png b/kallithea/public/images/icons/time.png rename from rhodecode/public/images/icons/time.png rename to kallithea/public/images/icons/time.png diff --git a/rhodecode/public/images/icons/time_add.png b/kallithea/public/images/icons/time_add.png rename from rhodecode/public/images/icons/time_add.png rename to kallithea/public/images/icons/time_add.png diff --git a/rhodecode/public/images/icons/time_delete.png b/kallithea/public/images/icons/time_delete.png rename from rhodecode/public/images/icons/time_delete.png rename to kallithea/public/images/icons/time_delete.png diff --git a/rhodecode/public/images/icons/time_go.png b/kallithea/public/images/icons/time_go.png rename from rhodecode/public/images/icons/time_go.png rename to kallithea/public/images/icons/time_go.png diff --git a/rhodecode/public/images/icons/timeline_marker.png b/kallithea/public/images/icons/timeline_marker.png rename from rhodecode/public/images/icons/timeline_marker.png rename to kallithea/public/images/icons/timeline_marker.png diff --git a/rhodecode/public/images/icons/transmit.png b/kallithea/public/images/icons/transmit.png rename from rhodecode/public/images/icons/transmit.png rename to kallithea/public/images/icons/transmit.png diff --git a/rhodecode/public/images/icons/transmit_add.png b/kallithea/public/images/icons/transmit_add.png rename from rhodecode/public/images/icons/transmit_add.png rename to kallithea/public/images/icons/transmit_add.png diff --git a/rhodecode/public/images/icons/transmit_blue.png b/kallithea/public/images/icons/transmit_blue.png rename from rhodecode/public/images/icons/transmit_blue.png rename to kallithea/public/images/icons/transmit_blue.png diff --git a/rhodecode/public/images/icons/transmit_delete.png b/kallithea/public/images/icons/transmit_delete.png rename from rhodecode/public/images/icons/transmit_delete.png rename to kallithea/public/images/icons/transmit_delete.png diff --git a/rhodecode/public/images/icons/transmit_edit.png b/kallithea/public/images/icons/transmit_edit.png rename from rhodecode/public/images/icons/transmit_edit.png rename to kallithea/public/images/icons/transmit_edit.png diff --git a/rhodecode/public/images/icons/transmit_error.png b/kallithea/public/images/icons/transmit_error.png rename from rhodecode/public/images/icons/transmit_error.png rename to kallithea/public/images/icons/transmit_error.png diff --git a/rhodecode/public/images/icons/transmit_go.png b/kallithea/public/images/icons/transmit_go.png rename from rhodecode/public/images/icons/transmit_go.png rename to kallithea/public/images/icons/transmit_go.png diff --git a/rhodecode/public/images/icons/trash_16.png b/kallithea/public/images/icons/trash_16.png rename from rhodecode/public/images/icons/trash_16.png rename to kallithea/public/images/icons/trash_16.png diff --git a/rhodecode/public/images/icons/tux.png b/kallithea/public/images/icons/tux.png rename from rhodecode/public/images/icons/tux.png rename to kallithea/public/images/icons/tux.png diff --git a/rhodecode/public/images/icons/up_16.png b/kallithea/public/images/icons/up_16.png rename from rhodecode/public/images/icons/up_16.png rename to kallithea/public/images/icons/up_16.png diff --git a/rhodecode/public/images/icons/user.png b/kallithea/public/images/icons/user.png rename from rhodecode/public/images/icons/user.png rename to kallithea/public/images/icons/user.png diff --git a/rhodecode/public/images/icons/user_16.png b/kallithea/public/images/icons/user_16.png rename from rhodecode/public/images/icons/user_16.png rename to kallithea/public/images/icons/user_16.png diff --git a/rhodecode/public/images/icons/user_add.png b/kallithea/public/images/icons/user_add.png rename from rhodecode/public/images/icons/user_add.png rename to kallithea/public/images/icons/user_add.png diff --git a/rhodecode/public/images/icons/user_comment.png b/kallithea/public/images/icons/user_comment.png rename from rhodecode/public/images/icons/user_comment.png rename to kallithea/public/images/icons/user_comment.png diff --git a/rhodecode/public/images/icons/user_delete.png b/kallithea/public/images/icons/user_delete.png rename from rhodecode/public/images/icons/user_delete.png rename to kallithea/public/images/icons/user_delete.png diff --git a/rhodecode/public/images/icons/user_edit.png b/kallithea/public/images/icons/user_edit.png rename from rhodecode/public/images/icons/user_edit.png rename to kallithea/public/images/icons/user_edit.png diff --git a/rhodecode/public/images/icons/user_female.png b/kallithea/public/images/icons/user_female.png rename from rhodecode/public/images/icons/user_female.png rename to kallithea/public/images/icons/user_female.png diff --git a/rhodecode/public/images/icons/user_go.png b/kallithea/public/images/icons/user_go.png rename from rhodecode/public/images/icons/user_go.png rename to kallithea/public/images/icons/user_go.png diff --git a/rhodecode/public/images/icons/user_gray.png b/kallithea/public/images/icons/user_gray.png rename from rhodecode/public/images/icons/user_gray.png rename to kallithea/public/images/icons/user_gray.png diff --git a/rhodecode/public/images/icons/user_green.png b/kallithea/public/images/icons/user_green.png rename from rhodecode/public/images/icons/user_green.png rename to kallithea/public/images/icons/user_green.png diff --git a/rhodecode/public/images/icons/user_orange.png b/kallithea/public/images/icons/user_orange.png rename from rhodecode/public/images/icons/user_orange.png rename to kallithea/public/images/icons/user_orange.png diff --git a/rhodecode/public/images/icons/user_red.png b/kallithea/public/images/icons/user_red.png rename from rhodecode/public/images/icons/user_red.png rename to kallithea/public/images/icons/user_red.png diff --git a/rhodecode/public/images/icons/user_suit.png b/kallithea/public/images/icons/user_suit.png rename from rhodecode/public/images/icons/user_suit.png rename to kallithea/public/images/icons/user_suit.png diff --git a/rhodecode/public/images/icons/vcard.png b/kallithea/public/images/icons/vcard.png rename from rhodecode/public/images/icons/vcard.png rename to kallithea/public/images/icons/vcard.png diff --git a/rhodecode/public/images/icons/vcard_add.png b/kallithea/public/images/icons/vcard_add.png rename from rhodecode/public/images/icons/vcard_add.png rename to kallithea/public/images/icons/vcard_add.png diff --git a/rhodecode/public/images/icons/vcard_delete.png b/kallithea/public/images/icons/vcard_delete.png rename from rhodecode/public/images/icons/vcard_delete.png rename to kallithea/public/images/icons/vcard_delete.png diff --git a/rhodecode/public/images/icons/vcard_edit.png b/kallithea/public/images/icons/vcard_edit.png rename from rhodecode/public/images/icons/vcard_edit.png rename to kallithea/public/images/icons/vcard_edit.png diff --git a/rhodecode/public/images/icons/vector.png b/kallithea/public/images/icons/vector.png rename from rhodecode/public/images/icons/vector.png rename to kallithea/public/images/icons/vector.png diff --git a/rhodecode/public/images/icons/vector_add.png b/kallithea/public/images/icons/vector_add.png rename from rhodecode/public/images/icons/vector_add.png rename to kallithea/public/images/icons/vector_add.png diff --git a/rhodecode/public/images/icons/vector_delete.png b/kallithea/public/images/icons/vector_delete.png rename from rhodecode/public/images/icons/vector_delete.png rename to kallithea/public/images/icons/vector_delete.png diff --git a/rhodecode/public/images/icons/wallet_16.png b/kallithea/public/images/icons/wallet_16.png rename from rhodecode/public/images/icons/wallet_16.png rename to kallithea/public/images/icons/wallet_16.png diff --git a/rhodecode/public/images/icons/wand.png b/kallithea/public/images/icons/wand.png rename from rhodecode/public/images/icons/wand.png rename to kallithea/public/images/icons/wand.png diff --git a/rhodecode/public/images/icons/warning_16.png b/kallithea/public/images/icons/warning_16.png rename from rhodecode/public/images/icons/warning_16.png rename to kallithea/public/images/icons/warning_16.png diff --git a/rhodecode/public/images/icons/warning_msg.png b/kallithea/public/images/icons/warning_msg.png rename from rhodecode/public/images/icons/warning_msg.png rename to kallithea/public/images/icons/warning_msg.png diff --git a/rhodecode/public/images/icons/weather_clouds.png b/kallithea/public/images/icons/weather_clouds.png rename from rhodecode/public/images/icons/weather_clouds.png rename to kallithea/public/images/icons/weather_clouds.png diff --git a/rhodecode/public/images/icons/weather_cloudy.png b/kallithea/public/images/icons/weather_cloudy.png rename from rhodecode/public/images/icons/weather_cloudy.png rename to kallithea/public/images/icons/weather_cloudy.png diff --git a/rhodecode/public/images/icons/weather_lightning.png b/kallithea/public/images/icons/weather_lightning.png rename from rhodecode/public/images/icons/weather_lightning.png rename to kallithea/public/images/icons/weather_lightning.png diff --git a/rhodecode/public/images/icons/weather_rain.png b/kallithea/public/images/icons/weather_rain.png rename from rhodecode/public/images/icons/weather_rain.png rename to kallithea/public/images/icons/weather_rain.png diff --git a/rhodecode/public/images/icons/weather_snow.png b/kallithea/public/images/icons/weather_snow.png rename from rhodecode/public/images/icons/weather_snow.png rename to kallithea/public/images/icons/weather_snow.png diff --git a/rhodecode/public/images/icons/weather_sun.png b/kallithea/public/images/icons/weather_sun.png rename from rhodecode/public/images/icons/weather_sun.png rename to kallithea/public/images/icons/weather_sun.png diff --git a/rhodecode/public/images/icons/webcam.png b/kallithea/public/images/icons/webcam.png rename from rhodecode/public/images/icons/webcam.png rename to kallithea/public/images/icons/webcam.png diff --git a/rhodecode/public/images/icons/webcam_add.png b/kallithea/public/images/icons/webcam_add.png rename from rhodecode/public/images/icons/webcam_add.png rename to kallithea/public/images/icons/webcam_add.png diff --git a/rhodecode/public/images/icons/webcam_delete.png b/kallithea/public/images/icons/webcam_delete.png rename from rhodecode/public/images/icons/webcam_delete.png rename to kallithea/public/images/icons/webcam_delete.png diff --git a/rhodecode/public/images/icons/webcam_error.png b/kallithea/public/images/icons/webcam_error.png rename from rhodecode/public/images/icons/webcam_error.png rename to kallithea/public/images/icons/webcam_error.png diff --git a/rhodecode/public/images/icons/world.png b/kallithea/public/images/icons/world.png rename from rhodecode/public/images/icons/world.png rename to kallithea/public/images/icons/world.png diff --git a/rhodecode/public/images/icons/world_add.png b/kallithea/public/images/icons/world_add.png rename from rhodecode/public/images/icons/world_add.png rename to kallithea/public/images/icons/world_add.png diff --git a/rhodecode/public/images/icons/world_delete.png b/kallithea/public/images/icons/world_delete.png rename from rhodecode/public/images/icons/world_delete.png rename to kallithea/public/images/icons/world_delete.png diff --git a/rhodecode/public/images/icons/world_edit.png b/kallithea/public/images/icons/world_edit.png rename from rhodecode/public/images/icons/world_edit.png rename to kallithea/public/images/icons/world_edit.png diff --git a/rhodecode/public/images/icons/world_go.png b/kallithea/public/images/icons/world_go.png rename from rhodecode/public/images/icons/world_go.png rename to kallithea/public/images/icons/world_go.png diff --git a/rhodecode/public/images/icons/world_link.png b/kallithea/public/images/icons/world_link.png rename from rhodecode/public/images/icons/world_link.png rename to kallithea/public/images/icons/world_link.png diff --git a/rhodecode/public/images/icons/wrench.png b/kallithea/public/images/icons/wrench.png rename from rhodecode/public/images/icons/wrench.png rename to kallithea/public/images/icons/wrench.png diff --git a/rhodecode/public/images/icons/wrench_orange.png b/kallithea/public/images/icons/wrench_orange.png rename from rhodecode/public/images/icons/wrench_orange.png rename to kallithea/public/images/icons/wrench_orange.png diff --git a/rhodecode/public/images/icons/xhtml.png b/kallithea/public/images/icons/xhtml.png rename from rhodecode/public/images/icons/xhtml.png rename to kallithea/public/images/icons/xhtml.png diff --git a/rhodecode/public/images/icons/xhtml_add.png b/kallithea/public/images/icons/xhtml_add.png rename from rhodecode/public/images/icons/xhtml_add.png rename to kallithea/public/images/icons/xhtml_add.png diff --git a/rhodecode/public/images/icons/xhtml_delete.png b/kallithea/public/images/icons/xhtml_delete.png rename from rhodecode/public/images/icons/xhtml_delete.png rename to kallithea/public/images/icons/xhtml_delete.png diff --git a/rhodecode/public/images/icons/xhtml_go.png b/kallithea/public/images/icons/xhtml_go.png rename from rhodecode/public/images/icons/xhtml_go.png rename to kallithea/public/images/icons/xhtml_go.png diff --git a/rhodecode/public/images/icons/xhtml_valid.png b/kallithea/public/images/icons/xhtml_valid.png rename from rhodecode/public/images/icons/xhtml_valid.png rename to kallithea/public/images/icons/xhtml_valid.png diff --git a/rhodecode/public/images/icons/zoom.png b/kallithea/public/images/icons/zoom.png rename from rhodecode/public/images/icons/zoom.png rename to kallithea/public/images/icons/zoom.png diff --git a/rhodecode/public/images/icons/zoom_in.png b/kallithea/public/images/icons/zoom_in.png rename from rhodecode/public/images/icons/zoom_in.png rename to kallithea/public/images/icons/zoom_in.png diff --git a/rhodecode/public/images/icons/zoom_out.png b/kallithea/public/images/icons/zoom_out.png rename from rhodecode/public/images/icons/zoom_out.png rename to kallithea/public/images/icons/zoom_out.png diff --git a/kallithea/public/images/kallithea-logo.png b/kallithea/public/images/kallithea-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ae05dab060a409b399cb807fd7d853a1e0779fde GIT binary patch literal 1767 zc$@*}1{nE?P)wR;Bko7E@ zJ^|(gF(-&Q0bw~S@M@Nj696ZOa{@aj824h<$+EG*CiT7NM-qgP zOZw_hB}WJbgTY`h7z_r3!C+hpA6NvJ$MZjbM)KuOUL$$s@_M}cHR4yR6tR;(+Nyab$#E?Xp z$seDzI1jLs?`)w?@hHmYPzK3-#X#0b2 zTy3cOaJ;W$BHNKN@E8Lq$a_sTCCUXVPqG^KagQ<%4Ee%Xo_+d4g{|gG-)~gN)qKh8 zFocB9AQK-rq13(_Y~bdy&4YYh8VLd$)PjiQXFyRbd>2+rNF6cp#__(6t?_$?$q*k! z^<*7gX|v>p`~7P`(8*r(1(iR)vBWjBhPJ7t8*3eO|902S_kj z0DIzXSP+TQ<{kvIS>)8ydh{8&@4b4+C_+m|5iAw{RYTD3Z~WXF%k4ohVNnKK+24jq z)-Kk>!hlKA%Y>2>zGFXdl706inQt}Cl5p!%QNJQ*goi#+YtP@Se89Q{vTrS~w;MT0}V$CX)(!?YMDk5u43@#zMs|#V@#u-^$T)@#X zt^>|jf_-}{0*=YrbrWME(0{}LIU(YJi9;I)q6Ztia@-%Z@%|*5%^Jp$|Eu;#w{Y)> zg)%LE3LIn66Hh>ne=RZwH*{qrE)r~)*ya=0KuWlk6DHZ|pfqPjZ4=LLJihkL=77{T$5Aq?VS=Vvk;=F zk-)IwrKXIhXK;ntl6eN`TjITi&%(f<7)W|!(Sl>aXfh|(q(;qHcI*fZ0-UR3nRt65&n-AV7QMj9faRTxY<|aAlO_F3o1(L`bn}g*XcC^6z)plE(r~` z#QHjY@~M=3%tuO2o{PdLM%MAIVIAQe@%LR-+&u`AwN&?YbB3|52o0u!jGKYEY|&TEiu_3TqUr$xT$HgQcx`(cv$6$?(SeLK)IG*I=GF`9f>CpuhkeM zlvkHWK%NPb1(0x}jtprhBW9j^ayI3?bjW}cA1zrk$`#zpN&H&j&g^j!7UFgPjfw?e z!Av~d%K#q`TeyydsMrIuXwMDZDm88sP#`v6dZ32%Sd6Z^;30Ed*T=k zldL9U$AVW!9_l^>h_Y4*@iT?cW6}Il2n~;B)VZ%t!vIW3oDzTOO6ef#J#?uc) zK+angH{$Euv!4Rnt}2vbuVS*eCu4~nLNzCM + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rhodecode/public/images/login.png b/kallithea/public/images/login.png rename from rhodecode/public/images/login.png rename to kallithea/public/images/login.png diff --git a/rhodecode/public/images/pager.png b/kallithea/public/images/pager.png rename from rhodecode/public/images/pager.png rename to kallithea/public/images/pager.png diff --git a/rhodecode/public/images/pager_selected.png b/kallithea/public/images/pager_selected.png rename from rhodecode/public/images/pager_selected.png rename to kallithea/public/images/pager_selected.png diff --git a/rhodecode/public/images/sprite.png b/kallithea/public/images/sprite.png rename from rhodecode/public/images/sprite.png rename to kallithea/public/images/sprite.png diff --git a/rhodecode/public/images/user14.png b/kallithea/public/images/user14.png rename from rhodecode/public/images/user14.png rename to kallithea/public/images/user14.png diff --git a/rhodecode/public/images/user16.png b/kallithea/public/images/user16.png rename from rhodecode/public/images/user16.png rename to kallithea/public/images/user16.png diff --git a/rhodecode/public/images/user20.png b/kallithea/public/images/user20.png rename from rhodecode/public/images/user20.png rename to kallithea/public/images/user20.png diff --git a/rhodecode/public/images/user24.png b/kallithea/public/images/user24.png rename from rhodecode/public/images/user24.png rename to kallithea/public/images/user24.png diff --git a/rhodecode/public/images/user30.png b/kallithea/public/images/user30.png rename from rhodecode/public/images/user30.png rename to kallithea/public/images/user30.png diff --git a/rhodecode/public/images/vertical-indicator.png b/kallithea/public/images/vertical-indicator.png rename from rhodecode/public/images/vertical-indicator.png rename to kallithea/public/images/vertical-indicator.png diff --git a/rhodecode/public/js/rhodecode.js b/kallithea/public/js/base.js rename from rhodecode/public/js/rhodecode.js rename to kallithea/public/js/base.js --- a/rhodecode/public/js/rhodecode.js +++ b/kallithea/public/js/base.js @@ -1,17 +1,11 @@ /** -RhodeCode JS Files +Kallithea JS Files **/ if (typeof console == "undefined" || typeof console.log == "undefined"){ console = { log: function() {} } } - -var str_repeat = function(i, m) { - for (var o = []; m > 0; o[--m] = i); - return o.join(''); -}; - /** * INJECT .format function into String * Usage: "My name is {0} {1}".format("Johny","Bravo") @@ -19,8 +13,7 @@ var str_repeat = function(i, m) { * Inspired by https://gist.github.com/1049426 */ String.prototype.format = function() { - - function format() { + function format() { var str = this; var len = arguments.length+1; var safe = undefined; @@ -29,18 +22,18 @@ String.prototype.format = function() { // For each {0} {1} {n...} replace with the argument in that position. If // the argument is an object or an array it will be stringified to JSON. for (var i=0; i < len; arg = arguments[i++]) { - safe = typeof arg === 'object' ? JSON.stringify(arg) : arg; - str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe); + safe = typeof arg === 'object' ? JSON.stringify(arg) : arg; + str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe); } return str; - } + } - // Save a reference of what may already exist under the property native. - // Allows for doing something like: if("".format.native) { /* use native */ } - format.native = String.prototype.format; + // Save a reference of what may already exist under the property native. + // Allows for doing something like: if("".format.native) { /* use native */ } + format.native = String.prototype.format; - // Replace the prototype property - return format; + // Replace the prototype property + return format; }(); @@ -50,12 +43,14 @@ String.prototype.strip = function(char) } return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), ''); } + String.prototype.lstrip = function(char) { if(char === undefined){ char = '\\s'; } return this.replace(new RegExp('^'+char+'+'),''); } + String.prototype.rstrip = function(char) { if(char === undefined){ char = '\\s'; @@ -63,95 +58,82 @@ String.prototype.rstrip = function(char) return this.replace(new RegExp(''+char+'+$'),''); } - +/* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill + under MIT license / public domain, see + https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */ if(!Array.prototype.indexOf) { - Array.prototype.indexOf = function(needle) { - for(var i = 0; i < this.length; i++) { - if(this[i] === needle) { - return i; + Array.prototype.indexOf = function (searchElement, fromIndex) { + if ( this === undefined || this === null ) { + throw new TypeError( '"this" is null or not defined' ); + } + + var length = this.length >>> 0; // Hack to convert object.length to a UInt32 + + fromIndex = +fromIndex || 0; + + if (Math.abs(fromIndex) === Infinity) { + fromIndex = 0; + } + + if (fromIndex < 0) { + fromIndex += length; + if (fromIndex < 0) { + fromIndex = 0; } } + + for (;fromIndex < length; fromIndex++) { + if (this[fromIndex] === searchElement) { + return fromIndex; + } + } + return -1; }; } -// IE(CRAP) doesn't support previousElementSibling -var prevElementSibling = function( el ) { - if( el.previousElementSibling ) { - return el.previousElementSibling; - } else { - while( el = el.previousSibling ) { - if( el.nodeType === 1 ) return el; +/* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Compatibility + under MIT license / public domain, see + https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */ +if (!Array.prototype.filter) +{ + Array.prototype.filter = function(fun /*, thisArg */) + { + "use strict"; + + if (this === void 0 || this === null) + throw new TypeError(); + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun !== "function") + throw new TypeError(); + + var res = []; + var thisArg = arguments.length >= 2 ? arguments[1] : void 0; + for (var i = 0; i < len; i++) + { + if (i in t) + { + var val = t[i]; + + // NOTE: Technically this should Object.defineProperty at + // the next index, as push can be affected by + // properties on Object.prototype and Array.prototype. + // But that method's new, and collisions should be + // rare, so use the more-compatible alternative. + if (fun.call(thisArg, val, i, t)) + res.push(val); + } } - } + + return res; + }; } /** - * SmartColorGenerator - * - *usage:: - * var CG = new ColorGenerator(); - * var col = CG.getColor(key); //returns array of RGB - * 'rgb({0})'.format(col.join(',') - * - * @returns {ColorGenerator} - */ -var ColorGenerator = function(){ - this.GOLDEN_RATIO = 0.618033988749895; - this.CURRENT_RATIO = 0.22717784590367374 // this can be random - this.HSV_1 = 0.75;//saturation - this.HSV_2 = 0.95; - this.color; - this.cacheColorMap = {}; -}; - -ColorGenerator.prototype = { - getColor:function(key){ - if(this.cacheColorMap[key] !== undefined){ - return this.cacheColorMap[key]; - } - else{ - this.cacheColorMap[key] = this.generateColor(); - return this.cacheColorMap[key]; - } - }, - _hsvToRgb:function(h,s,v){ - if (s == 0.0) - return [v, v, v]; - i = parseInt(h * 6.0) - f = (h * 6.0) - i - p = v * (1.0 - s) - q = v * (1.0 - s * f) - t = v * (1.0 - s * (1.0 - f)) - i = i % 6 - if (i == 0) - return [v, t, p] - if (i == 1) - return [q, v, p] - if (i == 2) - return [p, v, t] - if (i == 3) - return [p, q, v] - if (i == 4) - return [t, p, v] - if (i == 5) - return [v, p, q] - }, - generateColor:function(){ - this.CURRENT_RATIO = this.CURRENT_RATIO+this.GOLDEN_RATIO; - this.CURRENT_RATIO = this.CURRENT_RATIO %= 1; - HSV_tuple = [this.CURRENT_RATIO, this.HSV_1, this.HSV_2] - RGB_tuple = this._hsvToRgb(HSV_tuple[0],HSV_tuple[1],HSV_tuple[2]); - function toRgb(v){ - return ""+parseInt(v*256) - } - return [toRgb(RGB_tuple[0]),toRgb(RGB_tuple[1]),toRgb(RGB_tuple[2])]; - - } -} - -/** - * PyRoutesJS + * A customized version of PyRoutes.JS from https://pypi.python.org/pypi/pyroutes.js/ + * which is copyright Stephane Klein and was made available under the BSD License. * * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/ */ @@ -291,7 +273,6 @@ var pyroutes = (function() { var route = matchlist[route_name]; // param substitution for(var i=0; i < route[1].length; i++) { - if (!params.hasOwnProperty(route[1][i])) throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation'); } @@ -319,8 +300,8 @@ var pyroutes = (function() { //fix escape route_tmpl = unescape(route_tmpl); keys = []; - for (o in req_params){ - keys.push(req_params[o]) + for (var i=0; i < req_params.length; i++) { + keys.push(req_params[i]) } matchlist[route_name] = [ route_tmpl, @@ -334,7 +315,6 @@ var pyroutes = (function() { })(); - /** * GLOBAL YUI Shortcuts */ @@ -343,16 +323,7 @@ var YUD = YAHOO.util.Dom; var YUE = YAHOO.util.Event; var YUQ = YAHOO.util.Selector.query; -// defines if push state is enabled for this browser ? -var push_state_enabled = Boolean( - window.history && window.history.pushState && window.history.replaceState - && !( /* disable for versions of iOS before version 4.3 (8F190) */ - (/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent) - /* disable for the mercury iOS browser, or at least older versions of the webkit engine */ - || (/AppleWebKit\/5([0-2]|3[0-2])/i).test(navigator.userAgent) - ) -); - +/* Invoke all functions in callbacks */ var _run_callbacks = function(callbacks){ if (callbacks !== undefined){ var _l = callbacks.length; @@ -370,7 +341,7 @@ var _run_callbacks = function(callbacks) /** * turns objects into GET query string */ -var toQueryString = function(o) { +var _toQueryString = function(o) { if(typeof o !== 'object') { return false; } @@ -403,6 +374,7 @@ function ypjax(url,container,s_call,f_ca if(args===undefined){ args=null; } + $container = $('#' + container); // Set special header for partial ajax == HTTP_X_PARTIAL_XHR YUC.initHeader('X-PARTIAL-XHR',true); @@ -410,21 +382,21 @@ function ypjax(url,container,s_call,f_ca // wrapper of passed callback var s_wrapper = (function(o){ return function(o){ - YUD.get(container).innerHTML=o.responseText; - YUD.setStyle(container,'opacity','1.0'); + $container.html(o.responseText); + $container.css('opacity','1.0'); //execute the given original callback if (s_call !== undefined){ s_call(o); } } })() - YUD.setStyle(container,'opacity','0.3'); + $container.css('opacity','0.3'); YUC.asyncRequest(method,url,{ success:s_wrapper, failure:function(o){ - console.log(o); - YUD.get(container).innerHTML='ERROR: {0}'.format(o.status); - YUD.setStyle(container,'opacity','1.0'); + console.log('ypjax failure: '+o); + $container.html('ERROR: {0}'.format(o.status)); + $container.css('opacity','1.0'); }, cache:false },args); @@ -449,8 +421,6 @@ var ajaxGET = function(url,success) { return request; }; - - var ajaxPOST = function(url,postData,success) { // Set special header for ajax == HTTP_X_PARTIAL_XHR YUC.initHeader('X-PARTIAL-XHR',true); @@ -462,230 +432,158 @@ var ajaxPOST = function(url,postData,suc alert("error"); }, }; - var postData = toQueryString(postData); + var postData = _toQueryString(postData); var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData); return request; }; /** - * tooltip activate - */ -var tooltip_activate = function(){ - yt = YAHOO.yuitip.main; - YUE.onDOMReady(yt.init); -}; - -/** - * show more + * activate .show_more links + * the .show_more must have an id that is the the id of an element to hide prefixed with _ + * the parentnode will be displayed */ var show_more_event = function(){ - YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){ - var el = e.target; - YUD.setStyle(YUD.get(el.id.substring(1)),'display',''); - YUD.setStyle(el.parentNode,'display','none'); + $('.show_more').click(function(e){ + var el = e.currentTarget; + $('#' + el.id.substring(1)).hide(); + $(el.parentNode).show(); }); }; /** - * show changeset tooltip + * activate .lazy-cs mouseover for showing changeset tooltip */ var show_changeset_tooltip = function(){ - YUE.on(YUD.getElementsByClassName('lazy-cs'), 'mouseover', function(e){ - var target = e.currentTarget; - var rid = YUD.getAttribute(target,'raw_id'); - var repo_name = YUD.getAttribute(target,'repo_name'); - var ttid = 'tt-'+rid; - var success = function(o){ - var json = JSON.parse(o.responseText); - YUD.addClass(target,'tooltip') - YUD.setAttribute(target, 'title',json['message']); - YAHOO.yuitip.main.show_yuitip(e, target); - } - if(rid && !YUD.hasClass(target, 'tooltip')){ - YUD.setAttribute(target,'id',ttid); - YUD.setAttribute(target, 'title',_TM['loading ...']); - YAHOO.yuitip.main.set_listeners(target); - YAHOO.yuitip.main.show_yuitip(e, target); - var url = pyroutes.url('changeset_info', {"repo_name":repo_name, "revision": rid}); - ajaxGET(url, success) + $('.lazy-cs').mouseover(function(e){ + var $target = $(e.currentTarget); + var rid = $target.attr('raw_id'); + var repo_name = $target.attr('repo_name'); + if(rid && !$target.hasClass('tooltip')){ + _show_tooltip(e, _TM['loading ...']); + var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": rid}); + ajaxGET(url, function(o){ + var json = JSON.parse(o.responseText); + $target.addClass('tooltip') + _show_tooltip(e, json['message']); + _activate_tooltip($target); + }); } }); }; -var onSuccessFollow = function(target){ - var f = YUD.get(target); - var f_cnt = YUD.get('current_followers_count'); - - if(YUD.hasClass(f, 'follow')){ - f.setAttribute('class','following'); - f.setAttribute('title',_TM['Stop following this repository']); - - if(f_cnt){ - var cnt = Number(f_cnt.innerHTML)+1; - f_cnt.innerHTML = cnt; +var _onSuccessFollow = function(target){ + var $target = $(target); + var $f_cnt = $('#current_followers_count'); + if($target.hasClass('follow')){ + $target.attr('class', 'following'); + $target.attr('title', _TM['Stop following this repository']); + if($f_cnt.html()){ + var cnt = Number($f_cnt.html())+1; + $f_cnt.html(cnt); } } else{ - f.setAttribute('class','follow'); - f.setAttribute('title',_TM['Start following this repository']); - if(f_cnt){ - var cnt = Number(f_cnt.innerHTML)-1; - f_cnt.innerHTML = cnt; + $target.attr('class', 'follow'); + $target.attr('title', _TM['Start following this repository']); + if($f_cnt.html()){ + var cnt = Number($f_cnt.html())-1; + $f_cnt.html(cnt); } } } -var toggleFollowingUser = function(target,fallows_user_id,token,user_id){ - args = 'follows_user_id='+fallows_user_id; +var toggleFollowingRepo = function(target, follows_repo_id, token, user_id){ + args = 'follows_repo_id='+follows_repo_id; args+= '&auth_token='+token; if(user_id != undefined){ args+="&user_id="+user_id; } - YUC.asyncRequest('POST',TOGGLE_FOLLOW_URL,{ - success:function(o){ - onSuccessFollow(target); - } - },args); + $.post(TOGGLE_FOLLOW_URL, args, function(data){ + _onSuccessFollow(target); + }); return false; -} - -var toggleFollowingRepo = function(target,fallows_repo_id,token,user_id){ - - args = 'follows_repo_id='+fallows_repo_id; - args+= '&auth_token='+token; - if(user_id != undefined){ - args+="&user_id="+user_id; - } - YUC.asyncRequest('POST',TOGGLE_FOLLOW_URL,{ - success:function(o){ - onSuccessFollow(target); - } - },args); - return false; -} +}; var showRepoSize = function(target, repo_name, token){ var args= 'auth_token='+token; - if(!YUD.hasClass(target, 'loaded')){ - YUD.get(target).innerHTML = _TM['Loading ...']; + if(!$("#" + target).hasClass('loaded')){ + $("#" + target).html(_TM['Loading ...']); var url = pyroutes.url('repo_size', {"repo_name":repo_name}); - YUC.asyncRequest('POST',url,{ - success:function(o){ - YUD.get(target).innerHTML = JSON.parse(o.responseText); - YUD.addClass(target, 'loaded'); - } - },args); + $.post(url, args, function(data) { + $("#" + target).html(data); + $("#" + target).addClass('loaded'); + }); } return false; -} +}; /** - * TOOLTIP IMPL. + * tooltips */ -YAHOO.namespace('yuitip'); -YAHOO.yuitip.main = { - - $: YAHOO.util.Dom.get, - bgColor: '#000', - speed: 0.3, - opacity: 0.9, - offset: [15,15], - useAnim: false, - maxWidth: 600, - add_links: false, - yuitips: [], +var tooltip_activate = function(){ + $(document).ready(_init_tooltip); +}; - set_listeners: function(tt){ - YUE.on(tt, 'mouseover', yt.show_yuitip, tt); - YUE.on(tt, 'mousemove', yt.move_yuitip, tt); - YUE.on(tt, 'mouseout', yt.close_yuitip, tt); - }, +var _activate_tooltip = function($tt){ + $tt.mouseover(_show_tooltip); + $tt.mousemove(_move_tooltip); + $tt.mouseout(_close_tooltip); +}; - init: function(){ - yt.tipBox = yt.$('tip-box'); - if(!yt.tipBox){ - yt.tipBox = document.createElement('div'); - document.body.appendChild(yt.tipBox); - yt.tipBox.id = 'tip-box'; - } +var _init_tooltip = function(){ + var $tipBox = $('#tip-box'); + if(!$tipBox.length){ + $tipBox = $('
') + $(document.body).append($tipBox); + } - YUD.setStyle(yt.tipBox, 'display', 'none'); - YUD.setStyle(yt.tipBox, 'position', 'absolute'); - if(yt.maxWidth !== null){ - YUD.setStyle(yt.tipBox, 'max-width', yt.maxWidth+'px'); - } - - var yuitips = YUD.getElementsByClassName('tooltip'); + $tipBox.hide(); + $tipBox.css('position', 'absolute'); + $tipBox.css('max-width', '600px'); - if(yt.add_links === true){ - var links = document.getElementsByTagName('a'); - var linkLen = links.length; - for(i=0;i'+ +/* return jQuery expression with a tr with body in 3rd column and class cls and id named after the body */ +var _table_tr = function(cls, body){ + // like:
... + // except new inlines which are different ... + var comment_id = ($(body).attr('id') || 'comment-new').split('comment-')[1]; + var tr_id = 'comment-tr-{0}'.format(comment_id); + return $((''+ ''+ ''+ '{2}'+ - '').format(id, cls, body); - _el.innerHTML = _html; - return _el.children[0].children[0].children[0]; -}; - -/** comments **/ -var removeInlineForm = function(form) { - form.parentNode.removeChild(form); + '').format(tr_id, cls, body)); }; -var createInlineForm = function(parent_tr, f_path, line) { - var tmpl = YUD.get('comment-inline-form-template').innerHTML; - tmpl = tmpl.format(f_path, line); - var form = tableTr('comment-form-inline',tmpl) +/** return jQuery expression with new inline form based on template **/ +var _createInlineForm = function(parent_tr, f_path, line) { + var $tmpl = $('#comment-inline-form-template').html().format(f_path, line); + var $form = _table_tr('comment-form-inline', $tmpl) // create event for hide button - form = new YAHOO.util.Element(form); - var form_hide_button = new YAHOO.util.Element(YUD.getElementsByClassName('hide-inline-form',null,form)[0]); - form_hide_button.on('click', function(e) { + $form.find('.hide-inline-form').click(function(e) { var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode; - if(YUD.hasClass(newtr.nextElementSibling,'inline-comments-button')){ - YUD.setStyle(newtr.nextElementSibling,'display',''); + if($(newtr).next().hasClass('inline-comments-button')){ + $(newtr).next().show(); } - removeInlineForm(newtr); - YUD.removeClass(parent_tr, 'form-open'); - YUD.removeClass(parent_tr, 'hl-comment'); - + $(newtr).remove(); + $(parent_tr).removeClass('form-open'); + $(parent_tr).removeClass('hl-comment'); }); - return form + return $form }; /** - * Inject inline comment for on given TR this tr should be always an .line - * tr containing the line. Code will detect comment, and always put the comment - * block at the very bottom + * Inject inline comment for an given TR. This tr should always be a .line . + * The form will be inject after any comments. */ var injectInlineForm = function(tr){ - if(!YUD.hasClass(tr, 'line')){ - return - } - var submit_url = AJAX_COMMENT_URL; - var _td = YUD.getElementsByClassName('code',null,tr)[0]; - if(YUD.hasClass(tr,'form-open') || YUD.hasClass(tr,'context') || YUD.hasClass(_td,'no-comment')){ - return - } - YUD.addClass(tr,'form-open'); - YUD.addClass(tr,'hl-comment'); - var node = YUD.getElementsByClassName('full_f_path',null,tr.parentNode.parentNode.parentNode)[0]; - var f_path = YUD.getAttribute(node,'path'); - var lineno = getLineNo(tr); - var form = createInlineForm(tr, f_path, lineno, submit_url); + $tr = $(tr); + if(!$tr.hasClass('line')){ + return + } + var submit_url = AJAX_COMMENT_URL; + var $td = $tr.find('.code'); + if($tr.hasClass('form-open') || $tr.hasClass('context') || $td.hasClass('no-comment')){ + return + } + $tr.addClass('form-open hl-comment'); + var $node = $tr.parent().parent().parent().find('.full_f_path'); + var f_path = $node.attr('path'); + var lineno = _getLineNo(tr); + var $form = _createInlineForm(tr, f_path, lineno, submit_url); - var parent = tr; - while (1){ - var n = parent.nextElementSibling; - // next element are comments ! - if(YUD.hasClass(n,'inline-comments')){ - parent = n; - } - else{ - break; - } - } - YUD.insertAfter(form,parent); - var f = YUD.get(form); - var overlay = YUD.getElementsByClassName('overlay',null,f)[0]; - var _form = YUD.getElementsByClassName('inline-form',null,f)[0]; + var $parent = $tr; + while ($parent.next().hasClass('inline-comments')){ + var $parent = $parent.next(); + } + $form.insertAfter($parent); + var $overlay = $form.find('.overlay'); + var $inlineform = $form.find('.inline-form'); + + $form.submit(function(e){ + e.preventDefault(); - YUE.on(YUD.get(_form), 'submit',function(e){ - YUE.preventDefault(e); + if(lineno === undefined){ + alert('missing line !'); + return + } + if(f_path === undefined){ + alert('missing file path !'); + return + } - //ajax submit - var text = YUD.get('text_'+lineno).value; - var postData = { - 'text':text, - 'f_path':f_path, - 'line':lineno - }; - - if(lineno === undefined){ - alert('missing line !'); - return - } - if(f_path === undefined){ - alert('missing file path !'); - return - } + var text = $('#text_'+lineno).val(); + if(text == ""){ + return + } - if(text == ""){ - return - } - - var success = function(o){ - YUD.removeClass(tr, 'form-open'); - removeInlineForm(f); - var json_data = JSON.parse(o.responseText); - renderInlineComment(json_data); - }; + if ($overlay.hasClass('overlay')){ + $overlay.css('width', $inlineform.offsetWidth + 'px'); + $overlay.css('height', $inlineform.offsetHeight + 'px'); + } + $overlay.addClass('submitting'); - if (YUD.hasClass(overlay,'overlay')){ - var w = _form.offsetWidth; - var h = _form.offsetHeight; - YUD.setStyle(overlay,'width',w+'px'); - YUD.setStyle(overlay,'height',h+'px'); - } - YUD.addClass(overlay, 'submitting'); - - ajaxPOST(submit_url, postData, success); - }); + var success = function(o){ + $tr.removeClass('form-open'); + $form.remove(); + var json_data = JSON.parse(o.responseText); + _renderInlineComment(json_data); + }; + var postData = { + 'text': text, + 'f_path': f_path, + 'line': lineno + }; + ajaxPOST(submit_url, postData, success); + }); - YUE.on('preview-btn_'+lineno, 'click', function(e){ - var _text = YUD.get('text_'+lineno).value; - if(!_text){ - return - } - var post_data = {'text': _text}; - YUD.addClass('preview-box_'+lineno, 'unloaded'); - YUD.get('preview-box_'+lineno).innerHTML = _TM['Loading ...']; - YUD.setStyle('edit-container_'+lineno, 'display', 'none'); - YUD.setStyle('preview-container_'+lineno, 'display', ''); + $('#preview-btn_'+lineno).click(function(e){ + var text = $('#text_'+lineno).val(); + if(!text){ + return + } + $('#preview-box_'+lineno).addClass('unloaded'); + $('#preview-box_'+lineno).html(_TM['Loading ...']); + $('#edit-container_'+lineno).hide(); + $('#preview-container_'+lineno).show(); - var url = pyroutes.url('changeset_comment_preview', {'repo_name': REPO_NAME}); - ajaxPOST(url,post_data,function(o){ - YUD.get('preview-box_'+lineno).innerHTML = o.responseText; - YUD.removeClass('preview-box_'+lineno, 'unloaded'); - }) - }) - YUE.on('edit-btn_'+lineno, 'click', function(e){ - YUD.setStyle('edit-container_'+lineno, 'display', ''); - YUD.setStyle('preview-container_'+lineno, 'display', 'none'); - }) + var url = pyroutes.url('changeset_comment_preview', {'repo_name': REPO_NAME}); + var post_data = {'text': text}; + ajaxPOST(url, post_data, function(o){ + $('#preview-box_'+lineno).html(o.responseText); + $('#preview-box_'+lineno).removeClass('unloaded'); + }) + }) + $('#edit-btn_'+lineno).click(function(e){ + $('#edit-container_'+lineno).show(); + $('#preview-container_'+lineno).hide(); + }) - - setTimeout(function(){ - // callbacks - tooltip_activate(); - MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno, + setTimeout(function(){ + // callbacks + tooltip_activate(); + MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno, _USERS_AC_DATA, _GROUPS_AC_DATA); - var _e = YUD.get('text_'+lineno); - if(_e){ - _e.focus(); - } - },10) + $('#text_'+lineno).focus(); + },10) }; var deleteComment = function(comment_id){ var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id); var postData = {'_method':'delete'}; var success = function(o){ - var n = YUD.get('comment-tr-'+comment_id); - var root = prevElementSibling(prevElementSibling(n)); - n.parentNode.removeChild(n); - - // scann nodes, and attach add button to last one only for TR - // which are the inline comments - if(root && root.tagName == 'TR'){ - placeAddButton(root); - } + var $deleted = $('#comment-tr-'+comment_id); + var $prev = $deleted.prev('tr'); + $deleted.remove(); + _placeAddButton($prev); } ajaxPOST(url,postData,success); } -var createInlineAddButton = function(tr){ - - var label = TRANSLATION_MAP['Add another comment']; - - var html_el = document.createElement('div'); - YUD.addClass(html_el, 'add-comment'); - html_el.innerHTML = '{0}'.format(label); - - var add = new YAHOO.util.Element(html_el); - add.on('click', function(e) { - injectInlineForm(tr); - }); - return add; -}; - -var getLineNo = function(tr) { +var _getLineNo = function(tr) { var line; - var o = tr.children[0].id.split('_'); - var n = tr.children[1].id.split('_'); + var o = $(tr).children()[0].id.split('_'); + var n = $(tr).children()[1].id.split('_'); if (n.length >= 2) { line = n[n.length-1]; @@ -950,79 +787,48 @@ var getLineNo = function(tr) { return line }; -var placeAddButton = function(target_tr){ - if(!target_tr){ - return +var _placeAddButton = function($line_tr){ + var $tr = $line_tr; + while ($tr.next().hasClass('inline-comments')){ + $tr.find('.add-comment').remove(); + $tr = $tr.next(); } - var last_node = target_tr; - //scann - while (1){ - var n = last_node.nextElementSibling; - // next element are comments ! - if(YUD.hasClass(n,'inline-comments')){ - last_node = n; - //also remove the comment button from previous - var comment_add_buttons = YUD.getElementsByClassName('add-comment',null,last_node); - for(var i=0;i{0}
'.format(label)); + $html_el.click(function(e) { + injectInlineForm($line_tr); + }); + $tr.find('.comment').after($html_el); +}; /** * Places the inline comment into the changeset block in proper line position */ -var placeInline = function(target_container,lineno,html){ - var lineid = "{0}_{1}".format(target_container,lineno); - var target_line = YUD.get(lineid); - var comment = new YAHOO.util.Element(tableTr('inline-comments',html)) +var _placeInline = function(target_id, lineno, html){ + var $td = $("#{0}_{1}".format(target_id, lineno)); - // check if there are comments already ! - var parent = target_line.parentNode; - var root_parent = parent; - while (1){ - var n = parent.nextElementSibling; - // next element are comments ! - if(YUD.hasClass(n,'inline-comments')){ - parent = n; - } - else{ - break; - } - } - // put in the comment at the bottom - YUD.insertAfter(comment,parent); + // check if there are comments already ! + var $line_tr = $td.parent(); // the tr + var $after_tr = $line_tr; + while ($after_tr.next().hasClass('inline-comments')){ + $after_tr = $after_tr.next(); + } + // put in the comment at the bottom + $after_tr.after(_table_tr('inline-comments', html)); - // scann nodes, and attach add button to last one - placeAddButton(root_parent); - - return target_line; + // scan nodes, and attach add button to last one + _placeAddButton($line_tr); } /** * make a single inline comment and place it inside */ -var renderInlineComment = function(json_data){ - try{ - var html = json_data['rendered_text']; - var lineno = json_data['line_no']; - var target_id = json_data['target_id']; - placeInline(target_id, lineno, html); - - }catch(e){ - console.log(e); - } +var _renderInlineComment = function(json_data){ + var html = json_data['rendered_text']; + var lineno = json_data['line_no']; + var target_id = json_data['target_id']; + _placeInline(target_id, lineno, html); } /** @@ -1033,27 +839,28 @@ var renderInlineComments = function(file // holding all comments for a FILE var box = file_comments[f]; - var target_id = YUD.getAttribute(box,'target_id'); - // actually comments with line numbers + var target_id = $(box).attr('target_id'); + // actual comments with line numbers var comments = box.children; for(var i=0; i matches_max){ @@ -1120,148 +923,137 @@ var fileBrowserListeners = function(curr } if(match.length >= matches_max){ match.push('{0}'.format(_TM['Search truncated'])); + break; } } } if(query != ""){ - YUD.setStyle('tbody','display','none'); - YUD.setStyle('tbody_filtered','display',''); + $('#tbody').hide(); + $('#tbody_filtered').show(); if (match.length==0){ match.push('{0}'.format(_TM['No matching files'])); } - YUD.get('tbody_filtered').innerHTML = match.join(""); + $('#tbody_filtered').html(match.join("")); } else{ - YUD.setStyle('tbody','display',''); - YUD.setStyle('tbody_filtered','display','none'); + $('#tbody').show(); + $('#tbody_filtered').hide(); } - } }; - YUE.on(YUD.get('filter_activate'),'click',function(){ - F.initFilter(); - }) - YUE.on(n_filter,'click',function(){ - if(YUD.hasClass(n_filter,'init')){ - n_filter.value = ''; - YUD.removeClass(n_filter,'init'); - } - }); - YUE.on(n_filter,'keyup',function(e){ - clearTimeout(F.filterTimeout); - F.filterTimeout = setTimeout(F.updateFilter(e),600); - }); + $('#filter_activate').click(function(){ + initFilter(); + }); + $node_filter.click(function(){ + if($node_filter.hasClass('init')){ + $node_filter.val(''); + $node_filter.removeClass('init'); + } + }); + $node_filter.keyup(function(e){ + clearTimeout(filterTimeout); + filterTimeout = setTimeout(updateFilter(e),600); + }); }; -var initCodeMirror = function(textAreadId,resetUrl){ - var myCodeMirror = CodeMirror.fromTextArea(YUD.get(textAreadId),{ - mode: "null", - lineNumbers:true, - indentUnit: 4 - }); - YUE.on('reset','click',function(e){ - window.location=resetUrl - }); +var initCodeMirror = function(textarea_id, resetUrl){ + var myCodeMirror = CodeMirror.fromTextArea($('#' + textarea_id)[0], { + mode: "null", + lineNumbers: true, + indentUnit: 4, + autofocus: true, + }); + $('#reset').click(function(e){ + window.location=resetUrl; + }); - YUE.on('file_enable','click',function(){ - YUD.setStyle('editor_container','display',''); - YUD.setStyle('upload_file_container','display','none'); - YUD.setStyle('filename_container','display',''); - }); + $('#file_enable').click(function(){ + $('#editor_container').show(); + $('#upload_file_container').hide(); + $('#filename_container').show(); + $('#set_mode_header').show(); + }); - YUE.on('upload_file_enable','click',function(){ - YUD.setStyle('editor_container','display','none'); - YUD.setStyle('upload_file_container','display',''); - YUD.setStyle('filename_container','display','none'); - }); + $('#upload_file_enable').click(function(){ + $('#editor_container').hide(); + $('#upload_file_container').show(); + $('#filename_container').hide(); + $('#set_mode_header').hide(); + }); return myCodeMirror }; var setCodeMirrorMode = function(codeMirrorInstance, mode) { - codeMirrorInstance.setOption("mode", mode); - CodeMirror.autoLoadMode(codeMirrorInstance, mode); + codeMirrorInstance.setOption("mode", mode); + CodeMirror.autoLoadMode(codeMirrorInstance, mode); } -var getIdentNode = function(n){ - //iterate thru nodes untill matched interesting node ! +var _getIdentNode = function(n){ + //iterate thrugh nodes until matching interesting node if (typeof n == 'undefined'){ return -1 } if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){ - return n - } + return n + } else{ - return getIdentNode(n.parentNode); + return _getIdentNode(n.parentNode); } }; -var getSelectionLink = function(e) { - +/* generate links for multi line selects that can be shown by files.html page_highlights. + * This is a mouseup handler for hlcode from CodeHtmlFormatter and pygmentize */ +var getSelectionLink = function(e) { //get selection from start/to nodes if (typeof window.getSelection != "undefined") { s = window.getSelection(); - from = getIdentNode(s.anchorNode); - till = getIdentNode(s.focusNode); + from = _getIdentNode(s.anchorNode); + till = _getIdentNode(s.focusNode); f_int = parseInt(from.id.replace('L','')); t_int = parseInt(till.id.replace('L','')); - if (f_int > t_int){ + var yoffset = 35; + var ranges = [parseInt(from.id.replace('L','')), parseInt(till.id.replace('L',''))]; + if (ranges[0] > ranges[1]){ //highlight from bottom - offset = -35; - ranges = [t_int,f_int]; - + yoffset = -yoffset; + ranges = [ranges[1], ranges[0]]; } - else{ - //highligth from top - offset = 35; - ranges = [f_int,t_int]; - } + var $hl_div = $('div#linktt'); // if we select more than 2 lines if (ranges[0] != ranges[1]){ - if(YUD.get('linktt') == null){ - hl_div = document.createElement('div'); - hl_div.id = 'linktt'; + if ($hl_div.length) { + $hl_div.html(''); + } else { + $hl_div = $('
'); + $('body').prepend($hl_div); } - hl_div.innerHTML = ''; - anchor = '#L'+ranges[0]+'-'+ranges[1]; - var link = document.createElement('a'); - link.href = location.href.substring(0,location.href.indexOf('#'))+anchor; - link.innerHTML = _TM['Selection link']; - hl_div.appendChild(link); - YUD.get('body').appendChild(hl_div); - - xy = YUD.getXY(till.id); - - YUD.addClass('linktt', 'hl-tip-box'); - YUD.setStyle('linktt','top',xy[1]+offset+'px'); - YUD.setStyle('linktt','left',xy[0]+'px'); - YUD.setStyle('linktt','visibility','visible'); - + $hl_div.append($('').html(_TM['Selection link']).attr('href', location.href.substring(0, location.href.indexOf('#')) + '#L' + ranges[0] + '-'+ranges[1])); + xy = $(till).offset(); + $hl_div.css('top', (xy.top + yoffset) + 'px').css('left', xy.left + 'px'); + $hl_div.show(); } else{ - YUD.setStyle('linktt','visibility','hidden'); + $hl_div.hide(); } } }; -var deleteNotification = function(url, notification_id,callbacks){ +var deleteNotification = function(url, notification_id, callbacks){ var callback = { success:function(o){ - var obj = YUD.get(String("notification_"+notification_id)); - if(obj.parentNode !== undefined){ - obj.parentNode.removeChild(obj); - } + $("#notification_"+notification_id).remove(); _run_callbacks(callbacks); }, failure:function(o){ @@ -1274,16 +1066,12 @@ var deleteNotification = function(url, n callback, postData); }; -var readNotification = function(url, notification_id,callbacks){ +var readNotification = function(url, notification_id, callbacks){ var callback = { success:function(o){ - var obj = YUD.get(String("notification_"+notification_id)); - YUD.removeClass(obj, 'unread'); - var r_button = YUD.getElementsByClassName('read-notification',null,obj.children[0])[0]; - - if(r_button.parentNode !== undefined){ - r_button.parentNode.removeChild(r_button); - } + var $obj = $("#notification_"+notification_id); + $obj.removeClass('unread'); + $obj.find('.read-notification').remove(); _run_callbacks(callbacks); }, failure:function(o){ @@ -1298,7 +1086,7 @@ var readNotification = function(url, not /** MEMBERS AUTOCOMPLETE WIDGET **/ -var MembersAutoComplete = function (divid, cont, users_list, groups_list) { +var _MembersAutoComplete = function (divid, cont, users_list, groups_list) { var myUsers = users_list; var myGroups = groups_list; @@ -1316,8 +1104,8 @@ var MembersAutoComplete = function (divi if (((contact.fname+"").toLowerCase().indexOf(query) > -1) || ((contact.lname+"").toLowerCase().indexOf(query) > -1) || ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) { - matches[matches.length] = contact; - } + matches[matches.length] = contact; + } } return matches; }; @@ -1453,11 +1241,11 @@ var MembersAutoComplete = function (divi if (oData.nname != undefined) { //users myAC.getInputEl().value = oData.nname; - YUD.get('perm_new_member_type_'+nextId).value = 'user'; + $('#perm_new_member_type_'+nextId).val('user'); } else { //groups myAC.getInputEl().value = oData.grname; - YUD.get('perm_new_member_type_'+nextId).value = 'users_group'; + $('#perm_new_member_type_'+nextId).val('users_group'); } }; @@ -1474,7 +1262,6 @@ var MembersAutoComplete = function (divi }; } - var MentionsAutoComplete = function (divid, cont, users_list, groups_list) { var myUsers = users_list; var myGroups = groups_list; @@ -1586,7 +1373,6 @@ var MentionsAutoComplete = function (div if(ownerAC.itemSelectEvent){ ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) { - var myAC = aArgs[0]; // reference back to the AC instance var elLI = aArgs[1]; // reference to the selected LI element var oData = aArgs[2]; // object literal of selected item's result data @@ -1601,11 +1387,11 @@ var MentionsAutoComplete = function (div chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery, '@'+oData.nname+' '); myAC.getInputEl().value = chunks.join('') - YUD.get(myAC.getInputEl()).focus(); // Y U NO WORK !? + myAC.getInputEl().focus(); // Y U NO WORK !? } else { //groups myAC.getInputEl().value = oData.grname; - YUD.get('perm_new_member_type').value = 'users_group'; + $('#perm_new_member_type').val('users_group'); } }); } @@ -1621,7 +1407,6 @@ var MentionsAutoComplete = function (div var re = new RegExp('(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)$') var chunks = []; - // cut first chunk until curret pos var to_max = msg.substr(0, max_pos); var at_pos = Math.max(0,to_max.lastIndexOf('@')-1); @@ -1641,12 +1426,10 @@ var MentionsAutoComplete = function (div return [null, null]; }; - if (ownerAC.textboxKeyUpEvent){ - ownerAC.textboxKeyUpEvent.subscribe(function(type, args){ - - var ac_obj = args[0]; - var currentMessage = args[1]; - var currentCaretPosition = args[0]._elTextbox.selectionStart; + $divid = $('#'+divid); + $divid.keyup(function(e){ + var currentMessage = $divid.val(); + var currentCaretPosition = $divid[0].selectionStart; var unam = ownerAC.get_mention(currentMessage, currentCaretPosition); var curr_search = null; @@ -1656,55 +1439,48 @@ var MentionsAutoComplete = function (div ownerAC.dataSource.chunks = unam[1]; ownerAC.dataSource.mentionQuery = curr_search; - - }) - } - return { - ownerDS: ownerDS, - ownerAC: ownerAC, - }; + }); } var addReviewMember = function(id,fname,lname,nname,gravatar_link){ - var members = YUD.get('review_members'); - var tmpl = '
  • '+ - '
    '+ - '
    gravatar
    '+ - '
    {1}
    '+ - ''+ - ''+ - '
    '+ - '
  • ' ; - var displayname = "{0} {1} ({2})".format(fname,lname,nname); - var element = tmpl.format(gravatar_link,displayname,id); + var displayname = "{0} {1} ({2})".format(fname, lname, nname); + var element = ( + '
  • \n'+ + '
    \n'+ + '
    \n'+ + ' \n'+ + '
    \n'+ + '
    gravatar
    \n'+ + '
    {1}
    \n'+ + ' \n'+ + '
    \n'+ + ' \n'+ + '
    \n'+ + '
    \n'+ + '
  • \n' + ).format(gravatar_link, displayname, id); // check if we don't have this ID already in var ids = []; - var _els = YUQ('#review_members li'); - for (el in _els){ - ids.push(_els[el].id) - } + $('#review_members').find('li').each(function() { + ids.push(this.id); + }); if(ids.indexOf('reviewer_'+id) == -1){ //only add if it's not there - members.innerHTML += element; + $('#review_members').append(element); } - } var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){ - var el = YUD.get('reviewer_{0}'.format(reviewer_id)); - if (el.parentNode !== undefined){ - el.parentNode.removeChild(el); - } + $('#reviewer_{0}'.format(reviewer_id)).remove(); } +/* handle "Save Changes" of addReviewMember and removeReviewMember on PR */ var updateReviewers = function(reviewers_ids, repo_name, pull_request_id){ if (reviewers_ids === undefined){ - var reviewers_ids = []; - var ids = YUQ('#review_members input'); - for(var i=0; i -1) || ((contact.lname+"").toLowerCase().indexOf(query) > -1) || ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) { - matches[matches.length] = contact; - } + matches[matches.length] = contact; + } } return matches; }; @@ -1849,37 +1626,32 @@ var PullRequestAutoComplete = function ( var oData = aArgs[2]; // object literal of selected item's result data //fill the autocomplete with value - if (oData.nname != undefined) { addReviewMember(oData.id, oData.fname, oData.lname, oData.nname, oData.gravatar_lnk); myAC.dataSource.cache.push(oData.id); - YUD.get('user').value = '' + $('#user').val(''); } }); } - return { - ownerDS: ownerDS, - reviewerAC: reviewerAC, - }; } /** - * QUICK REPO MENU + * Activate .quick_repo_menu */ var quick_repo_menu = function(){ - YUE.on(YUQ('.quick_repo_menu'),'mouseenter',function(e){ - var menu = e.currentTarget.firstElementChild.firstElementChild; - if(YUD.hasClass(menu,'hidden')){ - YUD.replaceClass(e.currentTarget,'hidden', 'active'); - YUD.replaceClass(menu, 'hidden', 'active'); + $(".quick_repo_menu").mouseenter(function(e) { + var $menu = $(e.currentTarget).children().first().children().first(); + if($menu.hasClass('hidden')){ + $menu.removeClass('hidden').addClass('active'); + $(e.currentTarget).removeClass('hidden').addClass('active'); } }) - YUE.on(YUQ('.quick_repo_menu'),'mouseleave',function(e){ - var menu = e.currentTarget.firstElementChild.firstElementChild; - if(YUD.hasClass(menu,'active')){ - YUD.replaceClass(e.currentTarget, 'active', 'hidden'); - YUD.replaceClass(menu, 'active', 'hidden'); + $(".quick_repo_menu").mouseleave(function(e) { + var $menu = $(e.currentTarget).children().first().children().first(); + if($menu.hasClass('active')){ + $menu.removeClass('active').addClass('hidden'); + $(e.currentTarget).removeClass('active').addClass('hidden'); } }) }; @@ -1889,163 +1661,54 @@ var quick_repo_menu = function(){ * TABLE SORTING */ -// returns a node from given html; -var fromHTML = function(html){ - var _html = document.createElement('element'); - _html.innerHTML = html; - return _html; -} -var get_rev = function(node){ - var n = node.firstElementChild.firstElementChild; +var revisionSort = function(a, b, desc, field) { + var a_ = parseInt(a.getData('last_rev_raw') || 0); + var b_ = parseInt(b.getData('last_rev_raw') || 0); - if (n===null){ - return -1 - } - else{ - out = n.firstElementChild.innerHTML.split(':')[0].replace('r',''); - return parseInt(out); - } -} - -var get_name = function(node){ - var name = node.firstElementChild.children[2].innerHTML; - return name -} -var get_group_name = function(node){ - var name = node.firstElementChild.children[1].innerHTML; - return name -} -var get_date = function(node){ - var date_ = YUD.getAttribute(node.firstElementChild,'date'); - return date_ -} + return YAHOO.util.Sort.compare(a_, b_, desc); +}; -var get_age = function(node){ - return node -} - -var get_link = function(node){ - return node.firstElementChild.text; -} - -var revisionSort = function(a, b, desc, field) { - - var a_ = fromHTML(a.getData(field)); - var b_ = fromHTML(b.getData(field)); +var ageSort = function(a, b, desc, field) { + // data is like: 1 day and 23 hours ago + var a_ = $(a.getData(field)).attr('date'); + var b_ = $(b.getData(field)).attr('date'); - // extract revisions from string nodes - a_ = get_rev(a_) - b_ = get_rev(b_) - - var comp = YAHOO.util.Sort.compare; - var compState = comp(a_, b_, desc); - return compState; -}; -var ageSort = function(a, b, desc, field) { - var a_ = fromHTML(a.getData(field)); - var b_ = fromHTML(b.getData(field)); - - // extract name from table - a_ = get_date(a_) - b_ = get_date(b_) - - var comp = YAHOO.util.Sort.compare; - var compState = comp(a_, b_, desc); - return compState; + return YAHOO.util.Sort.compare(a_, b_, desc); }; var lastLoginSort = function(a, b, desc, field) { - var a_ = a.getData('last_login_raw') || 0; - var b_ = b.getData('last_login_raw') || 0; + var a_ = parseFloat(a.getData('last_login_raw') || 0); + var b_ = parseFloat(b.getData('last_login_raw') || 0); - var comp = YAHOO.util.Sort.compare; - var compState = comp(a_, b_, desc); - return compState; + return YAHOO.util.Sort.compare(a_, b_, desc); }; var nameSort = function(a, b, desc, field) { var a_ = a.getData('raw_name') || 0; var b_ = b.getData('raw_name') || 0; - var comp = YAHOO.util.Sort.compare; - var compState = comp(a_, b_, desc); - return compState; -}; - -var permNameSort = function(a, b, desc, field) { - var a_ = fromHTML(a.getData(field)); - var b_ = fromHTML(b.getData(field)); - // extract name from table - - a_ = a_.children[0].innerHTML; - b_ = b_.children[0].innerHTML; - - var comp = YAHOO.util.Sort.compare; - var compState = comp(a_, b_, desc); - return compState; + return YAHOO.util.Sort.compare(a_, b_, desc); }; -var groupNameSort = function(a, b, desc, field) { - var a_ = fromHTML(a.getData(field)); - var b_ = fromHTML(b.getData(field)); - - // extract name from table - a_ = get_group_name(a_) - b_ = get_group_name(b_) +var dateSort = function(a, b, desc, field) { + var a_ = parseFloat(a.getData('raw_date') || 0); + var b_ = parseFloat(b.getData('raw_date') || 0); - var comp = YAHOO.util.Sort.compare; - var compState = comp(a_, b_, desc); - return compState; -}; -var dateSort = function(a, b, desc, field) { - var a_ = fromHTML(a.getData(field)); - var b_ = fromHTML(b.getData(field)); - - // extract name from table - a_ = get_date(a_) - b_ = get_date(b_) - - var comp = YAHOO.util.Sort.compare; - var compState = comp(a_, b_, desc); - return compState; + return YAHOO.util.Sort.compare(a_, b_, desc); }; -var usernamelinkSort = function(a, b, desc, field) { - var a_ = fromHTML(a.getData(field)); - var b_ = fromHTML(b.getData(field)); - - // extract url text from string nodes - a_ = get_link(a_) - b_ = get_link(b_) - var comp = YAHOO.util.Sort.compare; - var compState = comp(a_, b_, desc); - return compState; +var addPermAction = function(_html, users_list, groups_list){ + var $last_node = $('.last_new_member').last(); // empty tr between last and add + var next_id = $('.new_members').length; + $last_node.before($('').append(_html.format(next_id))); + _MembersAutoComplete("perm_new_member_name_"+next_id, + "perm_container_"+next_id, users_list, groups_list); } -var addPermAction = function(_html, users_list, groups_list){ - var elmts = YUD.getElementsByClassName('last_new_member'); - var last_node = elmts[elmts.length-1]; - if (last_node){ - var next_id = (YUD.getElementsByClassName('new_members')).length; - _html = _html.format(next_id); - last_node.innerHTML = _html; - YUD.setStyle(last_node, 'display', ''); - YUD.removeClass(last_node, 'last_new_member'); - MembersAutoComplete("perm_new_member_name_"+next_id, - "perm_container_"+next_id, users_list, groups_list); - //create new last NODE - var el = document.createElement('tr'); - el.id = 'add_perm_input'; - YUD.addClass(el,'last_new_member'); - YUD.addClass(el,'new_members'); - YUD.insertAfter(el, last_node); - } -} function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) { var callback = { success: function (o) { - var tr = YUD.get(String(field_id)); - tr.parentNode.removeChild(tr); + $('#' + field_id).remove(); }, failure: function (o) { alert(_TM['Failed to remoke permission'] + ": " + o.status); @@ -2071,142 +1734,44 @@ function ajaxActionRevokePermission(url, } var request = YAHOO.util.Connect.asyncRequest('POST', url, callback, - toQueryString(query_params)); + _toQueryString(query_params)); }; + /* Multi selectors */ var MultiSelectWidget = function(selected_id, available_id, form_id){ - - - //definition of containers ID's - var selected_container = selected_id; - var available_container = available_id; - - //temp container for selected storage. - var cache = new Array(); - var av_cache = new Array(); - var c = YUD.get(selected_container); - var ac = YUD.get(available_container); - - //get only selected options for further fullfilment - for(var i = 0;node =c.options[i];i++){ - if(node.selected){ - //push selected to my temp storage left overs :) - cache.push(node); - } - } - - //get all available options to cache - for(var i = 0;node =ac.options[i];i++){ - //push selected to my temp storage left overs :) - av_cache.push(node); - } - - //fill available only with those not in chosen - ac.options.length=0; - tmp_cache = new Array(); + var $availableselect = $('#' + available_id); + var $selectedselect = $('#' + selected_id); - for(var i = 0;node = av_cache[i];i++){ - var add = true; - for(var i2 = 0;node_2 = cache[i2];i2++){ - if(node.value == node_2.value){ - add=false; - break; - } - } - if(add){ - tmp_cache.push(new Option(node.text, node.value, false, false)); - } - } - - for(var i = 0;node = tmp_cache[i];i++){ - ac.options[i] = node; - } - - function prompts_action_callback(e){ - - var chosen = YUD.get(selected_container); - var available = YUD.get(available_container); - - //get checked and unchecked options from field - function get_checked(from_field){ - //temp container for storage. - var sel_cache = new Array(); - var oth_cache = new Array(); - - for(var i = 0;node = from_field.options[i];i++){ - if(node.selected){ - //push selected fields :) - sel_cache.push(node); - } - else{ - oth_cache.push(node) + //fill available only with those not in selected + var $selectedoptions = $selectedselect.children('option'); + $availableselect.children('option').filter(function(i, e){ + for(var j = 0, node; node = $selectedoptions[j]; j++){ + if(node.value == e.value){ + return true; } } - - return [sel_cache,oth_cache] - } - - //fill the field with given options - function fill_with(field,options){ - //clear firtst - field.options.length=0; - for(var i = 0;node = options[i];i++){ - field.options[i]=new Option(node.text, node.value, - false, false); - } - - } - //adds to current field - function add_to(field,options){ - for(var i = 0;node = options[i];i++){ - field.appendChild(new Option(node.text, node.value, - false, false)); - } - } + return false; + }).remove(); - // add action - if (this.id=='add_element'){ - var c = get_checked(available); - add_to(chosen,c[0]); - fill_with(available,c[1]); - } - // remove action - if (this.id=='remove_element'){ - var c = get_checked(chosen); - add_to(available,c[0]); - fill_with(chosen,c[1]); - } - // add all elements - if(this.id=='add_all_elements'){ - for(var i=0; node = available.options[i];i++){ - chosen.appendChild(new Option(node.text, - node.value, false, false)); - } - available.options.length = 0; - } - //remove all elements - if(this.id=='remove_all_elements'){ - for(var i=0; node = chosen.options[i];i++){ - available.appendChild(new Option(node.text, - node.value, false, false)); - } - chosen.options.length = 0; - } + $('#add_element').click(function(e){ + $selectedselect.append($availableselect.children('option:selected')); + }); + $('#remove_element').click(function(e){ + $availableselect.append($selectedselect.children('option:selected')); + }); + $('#add_all_elements').click(function(e){ + $selectedselect.append($availableselect.children('option')); + }); + $('#remove_all_elements').click(function(e){ + $availableselect.append($selectedselect.children('option')); + }); - } - - YUE.addListener(['add_element','remove_element', - 'add_all_elements','remove_all_elements'],'click', - prompts_action_callback) - if (form_id !== undefined) { - YUE.addListener(form_id,'submit',function(){ - var chosen = YUD.get(selected_container); - for (var i = 0; i < chosen.options.length; i++) { - chosen.options[i].selected = 'selected'; - } + $('#'+form_id).submit(function(){ + $selectedselect.children('option').each(function(i, e){ + e.selected = 'selected'; + }); }); - } } // custom paginator @@ -2278,7 +1843,7 @@ var YUI_paginator = function(links_per_p this.link = document.createElement('a'); this.span = document.createElement('span'); - YUD.setStyle(this.span, 'display', 'none'); + $(this.span).hide(); var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5); this.leftmost_page = _pos[0]; @@ -2289,7 +1854,7 @@ var YUI_paginator = function(links_per_p this.link.className = c; this.link.innerHTML = label; this.link.title = title; - YAHOO.util.Event.on(this.link,'click',this.onClick,this,true); + YUE.on(this.link,'click',this.onClick,this,true); setId(this.span, id_base + '-first-span'); this.span.className = c; @@ -2322,17 +1887,18 @@ var YUI_paginator = function(links_per_p } }, destroy : function () { - YAHOO.util.Event.purgeElement(this.link); + YUE.purgeElement(this.link); this.current.parentNode.removeChild(this.current); this.link = this.span = null; }, onClick : function (e) { - YAHOO.util.Event.stopEvent(e); + YUE.stopEvent(e); this.paginator.setPage(1); } }; })(); + (function () { var Paginator = YAHOO.widget.Paginator, @@ -2406,7 +1972,7 @@ var YUI_paginator = function(links_per_p this.link = document.createElement('a'); this.span = document.createElement('span'); - YUD.setStyle(this.span, 'display', 'none'); + $(this.span).hide(); this.na = this.span.cloneNode(false); @@ -2415,7 +1981,7 @@ var YUI_paginator = function(links_per_p this.link.className = c; this.link.innerHTML = label; this.link.title = title; - YAHOO.util.Event.on(this.link,'click',this.onClick,this,true); + YUE.on(this.link,'click',this.onClick,this,true); setId(this.span, id_base + '-last-span'); this.span.className = c; @@ -2464,12 +2030,12 @@ var YUI_paginator = function(links_per_p }, destroy : function () { - YAHOO.util.Event.purgeElement(this.link); + YUE.purgeElement(this.link); this.current.parentNode.removeChild(this.current); this.link = this.span = null; }, onClick : function (e) { - YAHOO.util.Event.stopEvent(e); + YUE.stopEvent(e); this.paginator.setPage(this.paginator.getTotalPages()); } }; @@ -2492,25 +2058,92 @@ var YUI_paginator = function(links_per_p return pagi } +var YUI_datatable = function(data, fields, columns, countnode, sortkey, rows){ + var myDataSource = new YAHOO.util.DataSource(data); + myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON; + myDataSource.responseSchema = { + resultsList: "records", + fields: fields, + }; + myDataSource.doBeforeCallback = function(req, raw, res, cb) { + // This is the filter function + var data = res.results || [], + filtered = [], + i, l; + if (req) { + req = req.toLowerCase(); + for (i = 0; i (this.$items.length - 1) || pos < 0) return + + if (this.sliding) return this.$element.one('slid', function () { that.to(pos) }) + if (activeIndex == pos) return this.pause().cycle() + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } + + Carousel.prototype.pause = function (e) { + e || (this.paused = true) + + if (this.$element.find('.next, .prev').length && $.support.transition.end) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + + this.interval = clearInterval(this.interval) + + return this + } + + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') + } + + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') + } + + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || $active[type]() + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var fallback = type == 'next' ? 'first' : 'last' + var that = this + + if (!$next.length) { + if (!this.options.wrap) return + $next = this.$element.find('.item')[fallback]() + } + + this.sliding = true + + isCycling && this.pause() + + var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) + + if ($next.hasClass('active')) return + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + + if ($.support.transition && this.$element.hasClass('slide')) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + $active + .one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { that.$element.trigger('slid') }, 0) + }) + .emulateTransitionEnd(600) + } else { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid') + } + + isCycling && this.cycle() + + return this + } + + + // CAROUSEL PLUGIN DEFINITION + // ========================== + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide + + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + $.fn.carousel.Constructor = Carousel + + + // CAROUSEL NO CONFLICT + // ==================== + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + + // CAROUSEL DATA-API + // ================= + + $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false + + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('bs.carousel').to(slideIndex) + } + + e.preventDefault() + }) + + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + $carousel.carousel($carousel.data()) + }) + }) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: collapse.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#collapse + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.transitioning = null + + if (this.options.parent) this.$parent = $(this.options.parent) + if (this.options.toggle) this.toggle() + } + + Collapse.DEFAULTS = { + toggle: true + } + + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return + + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var actives = this.$parent && this.$parent.find('> .panel > .in') + + if (actives && actives.length) { + var hasData = actives.data('bs.collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('bs.collapse', null) + } + + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + .addClass('collapsing') + [dimension](0) + + this.transitioning = 1 + + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('in') + [dimension]('auto') + this.transitioning = 0 + this.$element.trigger('shown.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + var scrollSize = $.camelCase(['scroll', dimension].join('-')) + + this.$element + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + [dimension](this.$element[0][scrollSize]) + } + + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return + + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var dimension = this.dimension() + + this.$element + [dimension](this.$element[dimension]()) + [0].offsetHeight + + this.$element + .addClass('collapsing') + .removeClass('collapse') + .removeClass('in') + + this.transitioning = 1 + + var complete = function () { + this.transitioning = 0 + this.$element + .trigger('hidden.bs.collapse') + .removeClass('collapsing') + .addClass('collapse') + } + + if (!$.support.transition) return complete.call(this) + + this.$element + [dimension](0) + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + } + + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + + // COLLAPSE PLUGIN DEFINITION + // ========================== + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.Constructor = Collapse + + + // COLLAPSE NO CONFLICT + // ==================== + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + // COLLAPSE DATA-API + // ================= + + $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + var target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + var $target = $(target) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() + var parent = $this.attr('data-parent') + var $parent = parent && $(parent) + + if (!data || !data.transitioning) { + if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') + $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + } + + $target.collapse(option) + }) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: dropdown.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#dropdowns + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle=dropdown]' + var Dropdown = function (element) { + var $el = $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we we use a backdrop because click events don't delegate + $('