# HG changeset patch # User Mads Kiilerich # Date 1431008669 -7200 # Node ID 7117a83b4b3a6efbe03fd0560f8206fed1cf63c7 # Parent 6101e27a7799f8fc52e8bc3b710ff34dbeeab56e# Parent a9d2e29585146ae77836c846ad2eacacdbd16f26 Merge stable diff -r a9d2e2958514 -r 7117a83b4b3a .hgignore --- a/.hgignore Thu May 07 16:23:45 2015 +0200 +++ b/.hgignore Thu May 07 16:24:29 2015 +0200 @@ -6,6 +6,8 @@ *.egg-info *.egg *.mo +.eggs/ +tarballcache/ syntax: regexp ^rcextensions diff -r a9d2e2958514 -r 7117a83b4b3a development.ini --- a/development.ini Thu May 07 16:23:45 2015 +0200 +++ b/development.ini Thu May 07 16:24:29 2015 +0200 @@ -134,7 +134,7 @@ host = 0.0.0.0 port = 5000 -## prefix middleware for rc +## middleware for hosting the WSGI application under a URL prefix #[filter:proxy-prefix] #use = egg:PasteDeploy#prefix #prefix = / diff -r a9d2e2958514 -r 7117a83b4b3a docs/index.rst --- a/docs/index.rst Thu May 07 16:23:45 2015 +0200 +++ b/docs/index.rst Thu May 07 16:24:29 2015 +0200 @@ -15,6 +15,7 @@ .. toctree:: :maxdepth: 1 + overview installation installation_win installation_win_old diff -r a9d2e2958514 -r 7117a83b4b3a docs/installation.rst --- a/docs/installation.rst Thu May 07 16:23:45 2015 +0200 +++ b/docs/installation.rst Thu May 07 16:24:29 2015 +0200 @@ -4,16 +4,11 @@ Installation on Unix/Linux ========================== -**Kallithea** is written entirely in Python_ and requires Python version -2.6 or higher. Python 3.x is currently not supported. - -There are several ways to install Kallithea: +Here are more details about 3 ways to install Kallithea: -- :ref:`installation-source`: The Kallithea development repository is stable - and can be used in production. In fact, the Kallithea maintainers do - use it in production. The advantage of installation from source and regularly - updating it is that you take advantage of the most recent improvements, which - is particularly useful because Kallithea is evolving rapidly. +- :ref:`installation-source`: The simplest way to keep the installation + uptodate and keep track of local customizations is to run directly from + source in a Kallithea repository clone and use virtualenv. - :ref:`installation-virtualenv`: If you prefer to only use released versions of Kallithea, the recommended method is to install Kallithea in a virtual @@ -205,5 +200,4 @@ .. _virtualenv: http://pypi.python.org/pypi/virtualenv -.. _Python: http://www.python.org/ .. _pylons: http://www.pylonsproject.org/ diff -r a9d2e2958514 -r 7117a83b4b3a docs/overview.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/overview.rst Thu May 07 16:24:29 2015 +0200 @@ -0,0 +1,128 @@ +.. _overview: + +===================== +Installation Overview +===================== + + +Some overview and some details that can help understanding the options when +installing Kallithea. + + +Python Environment +------------------ + +**Kallithea** is written entirely in Python_ and requires Python version +2.6 or higher. Python 3.x is currently not supported. + +Given a Python installation, there are different ways of providing the +environment for running Python applications. Each of them pretty much +corresponds to a ``site-packages`` directory somewhere where packages can be +installed. + +Kallithea itself can be run from source or be installed, but even when running +from source, there are some dependencies that must be installed in the Python +environment used for running Kallithea. + +- Packages *could* be installed in Python's ``site-packages`` directory ... but + that would require running pip_ as root and it would be hard to uninstall or + upgrade and is probably not a good idea unless using a package manager. + +- Packages could also be installed in ``~/.local`` ... but that is probably + only a good idea if using a dedicated user per application or instance. + +- Finally, it can be installed in a virtualenv_. That is a very lightweight + "container" where each Kallithea instance can get its own dedicated and + self-contained virtual environment. + +We recommend using virtualenv for installing Kallithea. + + +Installation Methods +-------------------- + +Kallithea must be installed on a server. Kallithea is installed in a Python +environment so it can use packages that are installed there and make itself +available for other packages. + +Two different cases will pretty much cover the options for how it can be +installed. + +- The Kallithea source repository can be cloned and used - it is kept stable and + can be used in production. The Kallithea maintainers use the development + branch in production. The advantage of installation from source and regularly + updating it is that you take advantage of the most recent improvements. Using + it directly from a DVCS also means that it is easy to track local customizations. + + Running ``setup.py develop`` in the source will use pip to install the + necessary dependencies in the Python environment and create a + ``.../site-packages/Kallithea.egg-link`` file there that points at the Kallithea + source. + +- Kallithea can also be installed from ready-made packages using a package manager. + The official released versions are available on PyPI_ and can be downloaded and + installed with all dependencies using ``pip install kallithea``. + + With this method, Kallithea is installed in the Python environment as any + other package, usually as a ``.../site-packages/Kallithea-X-py2.7.egg/`` + directory with Python files and everything else that is needed. + + (``pip install kallithea`` from a source tree will do pretty much the same + but build the Kallithea package itself locally instead of downloading it.) + + +Web Server +---------- + +Kallithea is (primarily) a WSGI_ application that must be run from a web +server that expose WSGI as HTTP. + +- Kallithea uses the Paste_ tool for some admin tasks. Paste provides ``paste + serve`` as a convenient way to launch Python WSGI / web servers. + This method is perfect for development but *can* also be used for production. + + ``paste`` is a command line tool. Using it in production requires some way to + wrap it as a managable service. + + Paste come with its own web server but Kallithea defaults to use Waitress_. + Gunicorn_ is also an option. These web servers have different limited feature + sets. + + It is also common/mandatory to put another web server or (reverse) proxy in + front of these Python web servers. Nginx_ is a common choice. This simple + setup will thus often end up being quite complex. + + The configuration of which web server to use is in the ini file passed to + ``paste``. The entry point for the WSGI application is configured in + ``setup.py`` as ``kallithea.config.middleware:make_app``. + +- `Apache httpd`_ can serve WSGI applications directly using mod_wsgi_ and a + simple Python file with the necessary configuration. This is a good option if + Apache is an option. + +- IIS_ can also server WSGI applications directly using isapi-wsgi_. + +- UWSGI_ is also an option. + +The best option depends on what you are familiar with and the requirements for +performance and stability. Also, keep in mind that Kallithea mainly is serving +custom data generated from relatively slow Python process. Kallithea is also +often used inside organizations with a limited amount of users and thus no +continuous hammering from the internet. + + +.. _Python: http://www.python.org/ +.. _Gunicorn: http://gunicorn.org/ +.. _Waitress: http://waitress.readthedocs.org/en/latest/ +.. _virtualenv: http://pypi.python.org/pypi/virtualenv +.. _Paste: http://pythonpaste.org/ +.. _PyPI: https://pypi.python.org/pypi +.. _Apache httpd: http://httpd.apache.org/ +.. _mod_wsgi: https://code.google.com/p/modwsgi/ +.. _isapi-wsgi: https://github.com/hexdump42/isapi-wsgi +.. _UWSGI: https://uwsgi-docs.readthedocs.org/en/latest/ +.. _nginx: http://nginx.org/en/ +.. _iis: http://en.wikipedia.org/wiki/Internet_Information_Services +.. _pip: http://en.wikipedia.org/wiki/Pip_%28package_manager%29 +.. _WSGI: http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface +.. _pylons: http://www.pylonsproject.org/ diff -r a9d2e2958514 -r 7117a83b4b3a docs/setup.rst --- a/docs/setup.rst Thu May 07 16:23:45 2015 +0200 +++ b/docs/setup.rst Thu May 07 16:24:29 2015 +0200 @@ -68,16 +68,21 @@ settings, as well as edit more advanced options on users and repositories + +Extensions +---------- + Optionally users can create an ``rcextensions`` package that extends Kallithea functionality. To do this simply execute:: paster make-rcext my.ini -This will create an ``rcextensions`` package in the same place that your ``ini`` file -lives. With ``rcextensions`` it's possible to add additional mapping for whoosh, +This will create an ``rcextensions`` package next to the specified ``ini`` file. +With ``rcextensions`` it's possible to add additional mapping for whoosh, stats and add additional code into the push/pull/create/delete repo hooks, -for example, for sending signals to build-bots such as Jenkins. -Please see the ``__init__.py`` file inside ``rcextensions`` package +for example for sending signals to build-bots such as Jenkins. + +See the ``__init__.py`` file inside the generated ``rcextensions`` package for more details. diff -r a9d2e2958514 -r 7117a83b4b3a docs/usage/performance.rst --- a/docs/usage/performance.rst Thu May 07 16:23:45 2015 +0200 +++ b/docs/usage/performance.rst Thu May 07 16:24:29 2015 +0200 @@ -39,7 +39,8 @@ sqlite is a good option when having a small load on the system. But due to locking issues with sqlite, it is not recommended to use it for larger deployments. Switching to mysql or postgres will result in an immediate - performance increase. + performance increase. A tool like SQLAlchemyGrate_ can be used for + migrating to another database platform. 3. Scale Kallithea horizontally @@ -61,3 +62,5 @@ - Load balance using round robin or IP hash, recommended is writing LB rules that will separate regular user traffic from automated processes like CI servers or build bots. + +.. _SQLAlchemyGrate: https://github.com/shazow/sqlalchemygrate diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/bin/template.ini.mako --- a/kallithea/bin/template.ini.mako Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/bin/template.ini.mako Thu May 07 16:24:29 2015 +0200 @@ -132,7 +132,7 @@ host = ${host} port = ${port} -<%text>## prefix middleware for rc +<%text>## middleware for hosting the WSGI application under a URL prefix #[filter:proxy-prefix] #use = egg:PasteDeploy#prefix #prefix = / diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/config/deployment.ini_tmpl --- a/kallithea/config/deployment.ini_tmpl Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/config/deployment.ini_tmpl Thu May 07 16:24:29 2015 +0200 @@ -129,7 +129,7 @@ host = 127.0.0.1 port = 5000 -## prefix middleware for rc +## middleware for hosting the WSGI application under a URL prefix #[filter:proxy-prefix] #use = egg:PasteDeploy#prefix #prefix = / diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/controllers/changeset.py --- a/kallithea/controllers/changeset.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/controllers/changeset.py Thu May 07 16:24:29 2015 +0200 @@ -349,7 +349,7 @@ @jsonify def comment(self, repo_name, revision): status = request.POST.get('changeset_status') - text = request.POST.get('text', '').strip() or _('No comments.') + text = request.POST.get('text', '').strip() c.co = comm = ChangesetCommentsModel().create( text=text, diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/controllers/error.py --- a/kallithea/controllers/error.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/controllers/error.py Thu May 07 16:24:29 2015 +0200 @@ -32,7 +32,7 @@ from pylons import tmpl_context as c, request, config from pylons.i18n.translation import _ -from pylons.middleware import media_path +from pylons.middleware import media_path from kallithea.lib.base import BaseController, render @@ -50,7 +50,7 @@ """ def __before__(self): - #disable all base actions since we don't need them here + # disable all base actions since we don't need them here pass def document(self): @@ -60,12 +60,16 @@ log.debug('### %s ###' % (resp and resp.status or 'no response')) e = request.environ - c.serv_p = r'%(protocol)s://%(host)s/' \ - % {'protocol': e.get('wsgi.url_scheme'), - 'host': e.get('HTTP_HOST'), } - - c.error_message = resp and cgi.escape(request.GET.get('code', str(resp.status))) - c.error_explanation = resp and self.get_error_explanation(resp.status_int) + c.serv_p = r'%(protocol)s://%(host)s/' % { + 'protocol': e.get('wsgi.url_scheme'), + 'host': e.get('HTTP_HOST'), } + if resp: + c.error_message = cgi.escape(request.GET.get('code', + str(resp.status))) + c.error_explanation = self.get_error_explanation(resp.status_int) + else: + c.error_message = _('No response') + c.error_explanation = _('Unknown error') return render('/errors/error_document.html') diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/controllers/pullrequests.py --- a/kallithea/controllers/pullrequests.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/controllers/pullrequests.py Thu May 07 16:24:29 2015 +0200 @@ -696,7 +696,7 @@ if allowed_to_change_status: status = request.POST.get('changeset_status') close_pr = request.POST.get('save_close') - text = request.POST.get('text', '').strip() or _('No comments.') + text = request.POST.get('text', '').strip() if close_pr: text = _('Closing.') + '\n' + text diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/i18n/be/LC_MESSAGES/kallithea.po --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/i18n/be/LC_MESSAGES/kallithea.po Thu May 07 16:24:29 2015 +0200 @@ -0,0 +1,5922 @@ +# Translations template for Kallithea. +# Copyright (C) 2015 Various authors, licensing as GPLv3 +# This file is distributed under the same license as the Kallithea project. +# Automatically generated, 2015. +# #, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Kallithea 0.1\n" +"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2015-04-01 03:17+0200\n" +"PO-Revision-Date: 2015-04-30 19:24+0200\n" +"Last-Translator: Viktar Palstsiuk \n" +"Language-Team: Belarusian " +"\n" +"Language: be\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\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" +"X-Generator: Weblate 2.3-dev\n" + +#: kallithea/controllers/changelog.py:86 +#: kallithea/controllers/pullrequests.py:247 kallithea/lib/base.py:449 +msgid "There are no changesets yet" +msgstr "Яшчэ не было змен" + +#: kallithea/controllers/changelog.py:157 +#: 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 "Нічога" + +#: kallithea/controllers/changelog.py:160 kallithea/controllers/files.py:197 +msgid "(closed)" +msgstr "(зачынена)" + +#: kallithea/controllers/changeset.py:89 +msgid "Show whitespace" +msgstr "Адлюстроўваць прабелы" + +#: kallithea/controllers/changeset.py:96 +#: kallithea/controllers/changeset.py:103 +#: kallithea/templates/files/diff_2way.html:55 +msgid "Ignore whitespace" +msgstr "Ігнараваць прабелы" + +#: kallithea/controllers/changeset.py:169 +#, python-format +msgid "increase diff context to %(num)s lines" +msgstr "павялічыць кантэкст да %(num)s радкоў" + +#: kallithea/controllers/changeset.py:212 kallithea/controllers/files.py:97 +#: kallithea/controllers/files.py:117 kallithea/controllers/files.py:746 +msgid "Such revision does not exist for this repository" +msgstr "Няма такой рэвізіі ў гэтым рэпазітары" + +#: kallithea/controllers/changeset.py:352 +#: kallithea/controllers/pullrequests.py:699 +msgid "No comments." +msgstr "Няма каментароў." + +#: kallithea/controllers/changeset.py:382 +msgid "" +"Changing status on a changeset associated with a closed pull request is not " +"allowed" +msgstr "Нельга рэдагаваць статут змен, злучаных з зачыненымі pull-request'ами" + +#: kallithea/controllers/compare.py:158 kallithea/templates/base/root.html:42 +msgid "Select changeset" +msgstr "Абраць набор змен" + +#: kallithea/controllers/compare.py:255 +msgid "Cannot compare repositories without using common ancestor" +msgstr "Немагчыма параўноўваць рэпазітары без агульнага продка" + +#: kallithea/controllers/error.py:96 +msgid "" +"The request could not be understood by the server due to malformed syntax." +msgstr "Запыт не распазнаны серверам з-за няправільнага сінтаксісу." + +#: kallithea/controllers/error.py:99 +msgid "Unauthorized access to resource" +msgstr "Несанкцыянаваны доступ да рэсурсу" + +#: kallithea/controllers/error.py:101 +msgid "You don't have permission to view this page" +msgstr "У вас няма правоў для прагляду гэтай старонкі" + +#: kallithea/controllers/error.py:103 +msgid "The resource could not be found" +msgstr "Рэсурс не знойдзены" + +#: kallithea/controllers/error.py:105 +msgid "" +"The server encountered an unexpected condition which prevented it from " +"fulfilling the request." +msgstr "Сервер не можа выканаць запыт з-за няправільнай умовы ў запыце." + +#: kallithea/controllers/feed.py:55 +#, python-format +msgid "Changes on %s repository" +msgstr "Змены ў рэпазітары %s" + +#: kallithea/controllers/feed.py:56 +#, python-format +msgid "%s %s feed" +msgstr "Стужка навін %s %s" + +#: kallithea/controllers/feed.py:89 +#: kallithea/templates/changeset/changeset.html:153 +#: kallithea/templates/changeset/changeset.html:166 +#: kallithea/templates/compare/compare_diff.html:78 +#: kallithea/templates/compare/compare_diff.html:89 +#: kallithea/templates/pullrequests/pullrequest_show.html:328 +#: kallithea/templates/pullrequests/pullrequest_show.html:351 +msgid "Changeset was too big and was cut off..." +msgstr "Змены апынуліся занадта вялікімі і былі выразаны..." + +#: kallithea/controllers/feed.py:93 +#, python-format +msgid "%s committed on %s" +msgstr "%s выканаў каміт у %s" + +#: 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 "Няма файлаў. %s" + +#: kallithea/controllers/files.py:194 +#, python-format +msgid "%s at %s" +msgstr "%s (%s)" + +#: kallithea/controllers/files.py:306 kallithea/controllers/files.py:366 +#: kallithea/controllers/files.py:433 +#, python-format +msgid "This repository has been locked by %s on %s" +msgstr "Рэпазітар заблакаваў %s у %s" + +#: kallithea/controllers/files.py:318 +msgid "You can only delete files with revision being a valid branch " +msgstr "Вы можаце выдаляць файлы толькі ў рэвізіі, злучанай з існай галінкай " + +#: kallithea/controllers/files.py:329 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "Файл %s выдалены з дапамогай Kallithea" + +#: kallithea/controllers/files.py:351 +#, python-format +msgid "Successfully deleted file %s" +msgstr "Файл %s выдалены" + +#: kallithea/controllers/files.py:355 kallithea/controllers/files.py:421 +#: kallithea/controllers/files.py:502 +msgid "Error occurred during commit" +msgstr "Падчас каміта адбылася памылка" + +#: kallithea/controllers/files.py:378 +msgid "You can only edit files with revision being a valid branch " +msgstr "Вы можаце рэдагаваць файлы толькі ў рэвізіі, злучанай з існай галінкай " + +#: kallithea/controllers/files.py:392 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "Файл %s адрэдагаваны з дапамогай Kallithea" + +#: kallithea/controllers/files.py:408 +msgid "No changes" +msgstr "Без змен" + +#: kallithea/controllers/files.py:417 kallithea/controllers/files.py:491 +#, python-format +msgid "Successfully committed to %s" +msgstr "Змены ўжыты ў %s" + +#: kallithea/controllers/files.py:444 +msgid "Added file via Kallithea" +msgstr "Файл дададзены з дапамогай Kallithea" + +#: kallithea/controllers/files.py:465 +msgid "No content" +msgstr "Пуста" + +#: kallithea/controllers/files.py:469 +msgid "No filename" +msgstr "Безназоўны" + +#: kallithea/controllers/files.py:494 +msgid "Location must be relative path and must not contain .. in path" +msgstr "" +"Размяшчэнне павінна быць адносным шляхам, і не павінна ўтрымоўваць \"..\" у " +"шляхі" + +#: kallithea/controllers/files.py:528 +msgid "Downloads disabled" +msgstr "Магчымасць спампоўваць адключана" + +#: kallithea/controllers/files.py:539 +#, python-format +msgid "Unknown revision %s" +msgstr "Невядомая рэвізія %s" + +#: kallithea/controllers/files.py:541 +msgid "Empty repository" +msgstr "Пусты рэпазітар" + +#: kallithea/controllers/files.py:543 +msgid "Unknown archive type" +msgstr "Невядомы тып архіва" + +#: kallithea/controllers/files.py:775 +#: kallithea/templates/changeset/changeset_range.html:9 +#: kallithea/templates/email_templates/pull_request.html:15 +#: kallithea/templates/pullrequests/pullrequest.html:116 +msgid "Changesets" +msgstr "Набор змен" + +#: kallithea/controllers/files.py:776 +#: kallithea/controllers/pullrequests.py:182 +#: kallithea/controllers/summary.py:74 kallithea/model/scm.py:816 +#: kallithea/templates/switch_to_list.html:3 +#: kallithea/templates/branches/branches.html:10 +msgid "Branches" +msgstr "Галінкі" + +#: kallithea/controllers/files.py:777 +#: kallithea/controllers/pullrequests.py:183 +#: kallithea/controllers/summary.py:75 kallithea/model/scm.py:827 +#: kallithea/templates/switch_to_list.html:25 +#: kallithea/templates/tags/tags.html:10 +msgid "Tags" +msgstr "Пазнакі" + +#: kallithea/controllers/forks.py:187 +#, python-format +msgid "An error occurred during repository forking %s" +msgstr "Адбылася памылка падчас стварэння форка рэпазітара %s" + +#: kallithea/controllers/home.py:84 +msgid "Groups" +msgstr "Групы" + +#: kallithea/controllers/home.py:89 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:106 +#: kallithea/templates/admin/repos/repo_add.html:12 +#: kallithea/templates/admin/repos/repo_add.html:16 +#: kallithea/templates/admin/repos/repos.html:9 +#: kallithea/templates/admin/users/user_edit_advanced.html:6 +#: kallithea/templates/base/base.html:60 kallithea/templates/base/base.html:77 +#: kallithea/templates/base/base.html:127 +#: kallithea/templates/base/base.html:390 +#: kallithea/templates/base/base.html:562 +msgid "Repositories" +msgstr "Рэпазітары" + +#: kallithea/controllers/home.py:130 +#: kallithea/templates/files/files_add.html:32 +#: kallithea/templates/files/files_delete.html:23 +#: kallithea/templates/files/files_edit.html:32 +msgid "Branch" +msgstr "Галінка" + +#: kallithea/controllers/home.py:136 +msgid "Tag" +msgstr "Тэгі" + +#: kallithea/controllers/home.py:142 +msgid "Bookmark" +msgstr "Закладкі" + +#: kallithea/controllers/journal.py:111 kallithea/controllers/journal.py:153 +msgid "public journal" +msgstr "агульнадаступны часопіс" + +#: kallithea/controllers/journal.py:115 kallithea/controllers/journal.py:157 +msgid "journal" +msgstr "часопіс" + +#: kallithea/controllers/login.py:188 kallithea/controllers/login.py:234 +msgid "bad captcha" +msgstr "няслушная капча" + +#: kallithea/controllers/login.py:194 +msgid "You have successfully registered into Kallithea" +msgstr "Рэгістрацыя ў Kallithea прайшла паспяхова" + +#: kallithea/controllers/login.py:239 +msgid "Your password reset link was sent" +msgstr "Спасылка для скіду пароля адпраўлена" + +#: kallithea/controllers/login.py:260 +msgid "" +"Your password reset was successful, new password has been sent to your email" +msgstr "Скід пароля выраблены, новы пароль быў адпраўлены на ваш email" + +#: kallithea/controllers/pullrequests.py:130 +#, python-format +msgid "%s (closed)" +msgstr "%s (зачынена)" + +#: kallithea/controllers/pullrequests.py:158 +#: kallithea/templates/changeset/changeset.html:12 +#: kallithea/templates/email_templates/changeset_comment.html:17 +msgid "Changeset" +msgstr "Змены" + +#: kallithea/controllers/pullrequests.py:179 +msgid "Special" +msgstr "Адмысловы" + +#: kallithea/controllers/pullrequests.py:180 +msgid "Peer branches" +msgstr "Галінкі ўдзельніка" + +#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:822 +#: kallithea/templates/switch_to_list.html:38 +#: kallithea/templates/bookmarks/bookmarks.html:10 +msgid "Bookmarks" +msgstr "Закладкі" + +#: kallithea/controllers/pullrequests.py:312 +#, python-format +msgid "Error creating pull request: %s" +msgstr "Памылка пры стварэнні pull-запыту: %s" + +#: kallithea/controllers/pullrequests.py:356 +#: kallithea/controllers/pullrequests.py:497 +msgid "No description" +msgstr "Няма апісання" + +#: kallithea/controllers/pullrequests.py:363 +msgid "Successfully opened new pull request" +msgstr "Pull-запыт створаны паспяхова" + +#: kallithea/controllers/pullrequests.py:366 +#: kallithea/controllers/pullrequests.py:450 +msgid "Error occurred while creating pull request" +msgstr "Адбылася памылка пры стварэнні pull-запыту" + +#: kallithea/controllers/pullrequests.py:398 +msgid "Missing changesets since the previous pull request:" +msgstr "Адсутныя рэвізіі адносна папярэдняга pull-запыту:" + +#: kallithea/controllers/pullrequests.py:405 +#, python-format +msgid "New changesets on %s %s since the previous pull request:" +msgstr "Новыя рэвізіі на %s %s адносна папярэдняга pull-запыту:" + +#: kallithea/controllers/pullrequests.py:412 +msgid "Ancestor didn't change - show diff since previous version:" +msgstr "" + +#: kallithea/controllers/pullrequests.py:419 +#, python-format +msgid "" +"This pull request is based on another %s revision and there is no simple " +"diff." +msgstr "Гэты pull-запыт заснаваны на іншай рэвізіі %s, просты diff немагчымы." + +#: kallithea/controllers/pullrequests.py:421 +#, python-format +msgid "No changes found on %s %s since previous version." +msgstr "Няма змен на %s %s адносна папярэдняй версіі." + +#: kallithea/controllers/pullrequests.py:456 +#, python-format +msgid "Closed, replaced by %s ." +msgstr "Зачынены, замешчаны %s ." + +#: kallithea/controllers/pullrequests.py:464 +msgid "Pull request update created" +msgstr "Абнаўленне для pull-запыту створана" + +#: kallithea/controllers/pullrequests.py:503 +msgid "Pull request updated" +msgstr "Pull-запыт абноўлены" + +#: kallithea/controllers/pullrequests.py:518 +msgid "Successfully deleted pull request" +msgstr "Pull-запыт паспяхова выдалены" + +#: kallithea/controllers/pullrequests.py:577 +#, python-format +msgid "This pull request has already been merged to %s." +msgstr "Гэты pull-запыт ужо прыняты на галінку %s." + +#: kallithea/controllers/pullrequests.py:579 +msgid "This pull request has been closed and can not be updated." +msgstr "Гэты pull-запыт быў зачынены і не можа быць абноўлены." + +#: kallithea/controllers/pullrequests.py:597 +#, python-format +msgid "This pull request can be updated with changes on %s:" +msgstr "Гэты pull-запыт можа быць абноўлены з %s:" + +#: kallithea/controllers/pullrequests.py:600 +msgid "No changesets found for updating this pull request." +msgstr "Няма змен для абнаўлення гэтага pull-запыту." + +#: kallithea/controllers/pullrequests.py:608 +#, python-format +msgid "Note: Branch %s has another head: %s." +msgstr "Увага: Галінка %s мае яшчэ адну верхавіну: %s." + +#: kallithea/controllers/pullrequests.py:614 +msgid "Git pull requests don't support updates yet." +msgstr "Абнаўленне pull-запыты git не падтрымліваецца." + +#: kallithea/controllers/pullrequests.py:701 +msgid "Closing." +msgstr "Зачынены." + +#: kallithea/controllers/search.py:135 +msgid "Invalid search query. Try quoting it." +msgstr "Недапушчальны пошукавы запыт. Паспрабуйце скласці яго ў двукоссі." + +#: kallithea/controllers/search.py:140 +msgid "There is no index to search in. Please run whoosh indexer" +msgstr "Індэксы адсутнічаюць. Калі ласка, запусціце індэксатар Whoosh" + +#: kallithea/controllers/search.py:144 +msgid "An error occurred during search operation." +msgstr "Адбылася памылка пры выкананні гэтага пошуку." + +#: kallithea/controllers/summary.py:199 +#: kallithea/templates/summary/summary.html:387 +msgid "No data ready yet" +msgstr "Няма дадзеных" + +#: kallithea/controllers/summary.py:202 +#: kallithea/templates/summary/summary.html:101 +msgid "Statistics are disabled for this repository" +msgstr "Статыстычныя дадзеныя адключаны для гэтага рэпазітара" + +#: kallithea/controllers/admin/auth_settings.py:125 +msgid "Auth settings updated successfully" +msgstr "Налады аўтарызацыі паспяхова абноўлены" + +#: kallithea/controllers/admin/auth_settings.py:136 +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:112 +msgid "Error occurred during update of defaults" +msgstr "Адбылася памылка пры абнаўленні стандартных налад" + +#: kallithea/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/my_account.py:238 +#: kallithea/controllers/admin/users.py:288 +msgid "forever" +msgstr "назаўжды" + +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:239 +#: kallithea/controllers/admin/users.py:289 +msgid "5 minutes" +msgstr "5 мінуць" + +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:240 +#: kallithea/controllers/admin/users.py:290 +msgid "1 hour" +msgstr "1 гадзіна" + +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:241 +#: kallithea/controllers/admin/users.py:291 +msgid "1 day" +msgstr "1 дзень" + +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:242 +#: kallithea/controllers/admin/users.py:292 +msgid "1 month" +msgstr "1 месяц" + +#: kallithea/controllers/admin/gists.py:67 +#: kallithea/controllers/admin/my_account.py:244 +#: kallithea/controllers/admin/users.py:294 +msgid "Lifetime" +msgstr "Тэрмін" + +#: kallithea/controllers/admin/gists.py:146 +msgid "Error occurred during gist creation" +msgstr "Адбылася памылка падчас стварэння gist-запісы" + +#: kallithea/controllers/admin/gists.py:184 +#, python-format +msgid "Deleted gist %s" +msgstr "Gist-запіс %s выдалена" + +#: kallithea/controllers/admin/gists.py:233 +msgid "unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:262 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:267 +msgid "Successfully updated gist data" +msgstr "Дадзеныя gist-запісы абноўлены" + +#: kallithea/controllers/admin/gists.py:270 +#, 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:128 +msgid "Your account was updated successfully" +msgstr "Ваш уліковы запіс паспяхова абноўлена" + +#: kallithea/controllers/admin/my_account.py:143 +#: kallithea/controllers/admin/users.py:206 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "Адбылася памылка пры абнаўленні карыстача %s" + +#: kallithea/controllers/admin/my_account.py:162 +msgid "Successfully updated password" +msgstr "Пароль абноўлены" + +#: kallithea/controllers/admin/my_account.py:173 +msgid "Error occurred during update of user password" +msgstr "Памылка пры абнаўленні пароля" + +#: kallithea/controllers/admin/my_account.py:215 +#: kallithea/controllers/admin/users.py:431 +#, python-format +msgid "Added email %s to user" +msgstr "Карыстачу дададзены e-mail %s" + +#: kallithea/controllers/admin/my_account.py:221 +#: kallithea/controllers/admin/users.py:437 +msgid "An error occurred during email saving" +msgstr "Адбылася памылка пры захаванні e-mail" + +#: kallithea/controllers/admin/my_account.py:230 +#: kallithea/controllers/admin/users.py:448 +msgid "Removed email from user" +msgstr "E-mail карыстача выдалены" + +#: kallithea/controllers/admin/my_account.py:254 +#: kallithea/controllers/admin/users.py:314 +msgid "Api key successfully created" +msgstr "API-ключ паспяхова створаны" + +#: kallithea/controllers/admin/my_account.py:266 +#: kallithea/controllers/admin/users.py:330 +msgid "Api key successfully reset" +msgstr "API-ключ паспяхова скінуты" + +#: kallithea/controllers/admin/my_account.py:270 +#: kallithea/controllers/admin/users.py:334 +msgid "Api key successfully deleted" +msgstr "API-ключ паспяхова выдалены" + +#: kallithea/controllers/admin/permissions.py:63 +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 +msgid "Read" +msgstr "Чытанне" + +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 +msgid "Write" +msgstr "Запіс" + +#: 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:9 +#: kallithea/templates/admin/defaults/defaults.html:9 +#: kallithea/templates/admin/permissions/permissions.html:9 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:9 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:9 +#: kallithea/templates/admin/repo_groups/repo_groups.html:10 +#: kallithea/templates/admin/repos/repo_add.html:10 +#: kallithea/templates/admin/repos/repo_add.html:14 +#: kallithea/templates/admin/repos/repos.html:9 +#: kallithea/templates/admin/settings/settings.html:9 +#: kallithea/templates/admin/user_groups/user_group_add.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit.html:9 +#: kallithea/templates/admin/user_groups/user_groups.html:10 +#: kallithea/templates/admin/users/user_add.html:8 +#: kallithea/templates/admin/users/user_edit.html:9 +#: kallithea/templates/admin/users/user_edit_profile.html:114 +#: kallithea/templates/admin/users/users.html:10 +#: kallithea/templates/admin/users/users.html:55 +#: kallithea/templates/base/base.html:255 +#: kallithea/templates/base/base.html:256 +#: kallithea/templates/base/base.html:262 +#: kallithea/templates/base/base.html:263 +msgid "Admin" +msgstr "Адміністратар" + +#: 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 "Адключана" + +#: 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: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:1684 +msgid "Manual activation of external account" +msgstr "Ручная актывацыя вонкавага ўліковага запісу" + +#: kallithea/controllers/admin/permissions.py:84 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1440 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1486 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1543 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1565 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1604 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1656 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1683 kallithea/model/db.py:1685 +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 "Уключана" + +#: kallithea/controllers/admin/permissions.py:125 +msgid "Global permissions updated successfully" +msgstr "Глабальныя прывілеі паспяхова абноўлены" + +#: kallithea/controllers/admin/permissions.py:140 +msgid "Error occurred during update of permissions" +msgstr "Адбылася памылка падчас абнаўлення прывілеяў" + +#: kallithea/controllers/admin/repo_groups.py:184 +#, python-format +msgid "Created repository group %s" +msgstr "Створана новая група рэпазітароў %s" + +#: kallithea/controllers/admin/repo_groups.py:197 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "Адбылася памылка пры стварэнні групы рэпазітароў %s" + +#: kallithea/controllers/admin/repo_groups.py:255 +#, 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 repositories 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:420 +#: kallithea/controllers/admin/repo_groups.py:455 +#: kallithea/controllers/admin/user_groups.py:340 +msgid "Cannot revoke permission for yourself as admin" +msgstr "Адміністратар не можа адклікаць свае прывелеі" + +#: kallithea/controllers/admin/repo_groups.py:435 +msgid "Repository Group permissions updated" +msgstr "Прывілеі групы рэпазітароў абноўлены" + +#: kallithea/controllers/admin/repo_groups.py:472 +#: kallithea/controllers/admin/repos.py:430 +#: kallithea/controllers/admin/user_groups.py:352 +msgid "An error occurred during revoking of permission" +msgstr "Адбылася памылка пры водгуку прывелеі" + +#: kallithea/controllers/admin/repos.py:163 +#, python-format +msgid "Error creating repository %s" +msgstr "Адбылася памылка пры стварэнні рэпазітара %s" + +#: kallithea/controllers/admin/repos.py:238 +#, python-format +msgid "Created repository %s from %s" +msgstr "Рэпазітар %s створаны з %s" + +#: kallithea/controllers/admin/repos.py:247 +#, python-format +msgid "Forked repository %s as %s" +msgstr "Зроблены форк(копія) рэпазітара %s на %s" + +#: kallithea/controllers/admin/repos.py:250 +#, python-format +msgid "Created repository %s" +msgstr "Рэпазітар %s створаны" + +#: kallithea/controllers/admin/repos.py:290 +#, python-format +msgid "Repository %s updated successfully" +msgstr "Рэпазітар %s паспяхова абноўлены" + +#: kallithea/controllers/admin/repos.py:309 +#, python-format +msgid "Error occurred during update of repository %s" +msgstr "Адбылася памылка падчас абнаўлення рэпазітара %s" + +#: kallithea/controllers/admin/repos.py:336 +#, python-format +msgid "Detached %s forks" +msgstr "Форки %s адлучаны" + +#: kallithea/controllers/admin/repos.py:339 +#, python-format +msgid "Deleted %s forks" +msgstr "Выдалены форки рэпазітара %s" + +#: kallithea/controllers/admin/repos.py:344 +#, python-format +msgid "Deleted repository %s" +msgstr "Рэпазітар %s выдалены" + +#: kallithea/controllers/admin/repos.py:347 +#, python-format +msgid "Cannot delete %s it still contains attached forks" +msgstr "Немагчыма выдаліць %s, ён усё-яшчэ ўтрымоўвае форки" + +#: kallithea/controllers/admin/repos.py:352 +#, python-format +msgid "An error occurred during deletion of %s" +msgstr "Адбылася памылка падчас выдалення %s" + +#: kallithea/controllers/admin/repos.py:406 +msgid "Repository permissions updated" +msgstr "Прывілеі рэпазітара абноўлены" + +#: kallithea/controllers/admin/repos.py:462 +msgid "An error occurred during creation of field" +msgstr "Адбылася памылка пры стварэнні поля" + +#: kallithea/controllers/admin/repos.py:476 +msgid "An error occurred during removal of field" +msgstr "Адбылася памылка пры выдаленні поля" + +#: kallithea/controllers/admin/repos.py:492 +msgid "-- Not a fork --" +msgstr "-- Не форк --" + +#: kallithea/controllers/admin/repos.py:526 +msgid "Updated repository visibility in public journal" +msgstr "Бачнасць рэпазітара ў публічным часопісе абноўлена" + +#: kallithea/controllers/admin/repos.py:530 +msgid "An error occurred during setting this repository in public journal" +msgstr "Адбылася памылка пры ўсталёўцы рэпазітара ў агульнадаступны часопіс" + +#: kallithea/controllers/admin/repos.py:535 kallithea/model/validators.py:340 +msgid "Token mismatch" +msgstr "Несупадзенне токенаў" + +#: kallithea/controllers/admin/repos.py:550 +msgid "Nothing" +msgstr "Нічога" + +#: kallithea/controllers/admin/repos.py:552 +#, python-format +msgid "Marked repo %s as fork of %s" +msgstr "Рэпазітар %s адзначаны як форк %s" + +#: kallithea/controllers/admin/repos.py:559 +msgid "An error occurred during this operation" +msgstr "Адбылася памылка пры выкананні аперацыі" + +#: kallithea/controllers/admin/repos.py:575 +msgid "Locked repository" +msgstr "Зачынены рэпазітар" + +#: kallithea/controllers/admin/repos.py:578 +msgid "Unlocked repository" +msgstr "Адкрыты рэпазітар" + +#: kallithea/controllers/admin/repos.py:581 +#: kallithea/controllers/admin/repos.py:608 +msgid "An error occurred during unlocking" +msgstr "Адбылася памылка падчас разблакавання" + +#: kallithea/controllers/admin/repos.py:599 +msgid "Unlocked" +msgstr "Разблакавана" + +#: kallithea/controllers/admin/repos.py:602 +msgid "Locked" +msgstr "Заблакавана" + +#: kallithea/controllers/admin/repos.py:604 +#, python-format +msgid "Repository has been %s" +msgstr "Рэпазітар %s" + +#: kallithea/controllers/admin/repos.py:622 +msgid "Cache invalidation successful" +msgstr "Кэш скінуты" + +#: kallithea/controllers/admin/repos.py:626 +msgid "An error occurred during cache invalidation" +msgstr "Адбылася памылка пры ачыстцы кэша" + +#: kallithea/controllers/admin/repos.py:641 +msgid "Pulled from remote location" +msgstr "Занесены змены з выдаленага рэпазітара" + +#: kallithea/controllers/admin/repos.py:644 +msgid "An error occurred during pull from remote location" +msgstr "Адбылася памылка пры занясенні змен з выдаленага рэпазітара" + +#: kallithea/controllers/admin/repos.py:677 +msgid "An error occurred during deletion of repository stats" +msgstr "Адбылася памылка пры выдаленні статыстыкі рэпазітара" + +#: kallithea/controllers/admin/settings.py:170 +msgid "Updated VCS settings" +msgstr "Абноўлены налады VCS" + +#: kallithea/controllers/admin/settings.py:174 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" +"Немагчыма ўключыць падтрымку hgsubversion. Бібліятэка «hgsubversion» " +"адсутнічае" + +#: kallithea/controllers/admin/settings.py:180 +#: kallithea/controllers/admin/settings.py:274 +msgid "Error occurred during updating application settings" +msgstr "Адбылася памылка пры абнаўленні налад прыкладання" + +#: kallithea/controllers/admin/settings.py:213 +#, python-format +msgid "Repositories successfully rescanned. Added: %s. Removed: %s." +msgstr "Рэпазітары паспяхова перасканіраваны, дададзена: %s, выдалена: %s." + +#: 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:373 +msgid "Send email task created" +msgstr "Задача адпраўкі Email створана" + +#: kallithea/controllers/admin/settings.py:404 +msgid "Added new hook" +msgstr "Дададзена новая пастка" + +#: kallithea/controllers/admin/settings.py:418 +msgid "Updated hooks" +msgstr "Абноўленыя пасткі" + +#: kallithea/controllers/admin/settings.py:422 +msgid "Error occurred during hook creation" +msgstr "адбылася памылка пры стварэнні хука" + +#: kallithea/controllers/admin/settings.py:448 +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:163 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "Адбылася памылка пры стварэнні групы карыстачоў %s" + +#: kallithea/controllers/admin/user_groups.py:201 +#, python-format +msgid "Updated user group %s" +msgstr "Група карыстачоў %s абноўлена" + +#: kallithea/controllers/admin/user_groups.py:224 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "Адбылася памылка пры абнаўленні групы карыстачоў %s" + +#: kallithea/controllers/admin/user_groups.py:242 +msgid "Successfully deleted user group" +msgstr "Група карыстачоў паспяхова выдалена" + +#: kallithea/controllers/admin/user_groups.py:247 +msgid "An error occurred during deletion of user group" +msgstr "Адбылася памылка пры выдаленні групы карыстачоў" + +#: kallithea/controllers/admin/user_groups.py:314 +msgid "Target group cannot be the same" +msgstr "Мэтавая група не можа быць такі ж" + +#: kallithea/controllers/admin/user_groups.py:320 +msgid "User Group permissions updated" +msgstr "Прывілеі групы карыстачоў абноўлены" + +#: kallithea/controllers/admin/user_groups.py:440 +#: kallithea/controllers/admin/users.py:396 +msgid "Updated permissions" +msgstr "Абноўлены прывілеі" + +#: kallithea/controllers/admin/user_groups.py:444 +#: kallithea/controllers/admin/users.py:400 +msgid "An error occurred during permissions saving" +msgstr "Адбылася памылка пры захаванні прывілеяў" + +#: kallithea/controllers/admin/users.py:132 +#, python-format +msgid "Created user %s" +msgstr "Карыстач %s створаны" + +#: kallithea/controllers/admin/users.py:147 +#, python-format +msgid "Error occurred during creation of user %s" +msgstr "Адбылася памылка пры стварэнні карыстача %s" + +#: kallithea/controllers/admin/users.py:186 +msgid "User updated successfully" +msgstr "Карыстач паспяхова абноўлены" + +#: kallithea/controllers/admin/users.py:222 +msgid "Successfully deleted user" +msgstr "Карыстач паспяхова выдалены" + +#: kallithea/controllers/admin/users.py:227 +msgid "An error occurred during deletion of user" +msgstr "Адбылася памылка пры выдаленні карыстача" + +#: kallithea/controllers/admin/users.py:241 +#: kallithea/controllers/admin/users.py:259 +#: kallithea/controllers/admin/users.py:282 +#: kallithea/controllers/admin/users.py:307 +#: kallithea/controllers/admin/users.py:320 +#: kallithea/controllers/admin/users.py:344 +#: kallithea/controllers/admin/users.py:407 +#: kallithea/controllers/admin/users.py:454 +msgid "You can't edit this user" +msgstr "Вы не можаце рэдагаваць дадзенага карыстача" + +#: kallithea/controllers/admin/users.py:482 +#, python-format +msgid "Added ip %s to user whitelist" +msgstr "Дададзены IP %s у белы спіс карыстача" + +#: kallithea/controllers/admin/users.py:488 +msgid "An error occurred during ip saving" +msgstr "Адбылася памылка пры захаванні IP" + +#: kallithea/controllers/admin/users.py:502 +msgid "Removed ip address from user whitelist" +msgstr "Выдалены IP %s з белага спісу карыстача" + +#: kallithea/lib/auth.py:745 +#, python-format +msgid "IP %s not allowed" +msgstr "IP %s заблакаваны" + +#: kallithea/lib/auth.py:806 +msgid "You need to be a registered user to perform this action" +msgstr "Вы павінны быць зарэгістраваным карыстачом, каб выканаць гэта дзеянне" + +#: kallithea/lib/auth.py:843 +msgid "You need to be signed in to view this page" +msgstr "Старонка даступная толькі аўтарызаваным карыстачам" + +#: kallithea/lib/base.py:427 +msgid "Repository not found in the filesystem" +msgstr "Рэпазітар не знойдзены на файлавай сістэме" + +#: kallithea/lib/base.py:453 kallithea/lib/helpers.py:643 +msgid "Changeset not found" +msgstr "Набор змен не знойдзены" + +#: 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 "" +"Набор змены апынуўся занадта вялікімі і быў падрэзаны, выкарыстоўвайце меню " +"параўнання для паказу выніку параўнання" + +#: kallithea/lib/diffs.py:92 +msgid "No changes detected" +msgstr "Змен не выяўлена" + +#: kallithea/lib/helpers.py:627 +#, python-format +msgid "Deleted branch: %s" +msgstr "Выдалена галінка: %s" + +#: kallithea/lib/helpers.py:630 +#, python-format +msgid "Created tag: %s" +msgstr "Створаны тэг: %s" + +#: kallithea/lib/helpers.py:693 +#, python-format +msgid "Show all combined changesets %s->%s" +msgstr "Паказаць адрозненні разам %s->%s" + +#: kallithea/lib/helpers.py:699 +msgid "compare view" +msgstr "параўнанне" + +#: kallithea/lib/helpers.py:718 +msgid "and" +msgstr "і" + +#: kallithea/lib/helpers.py:719 +#, python-format +msgid "%s more" +msgstr "на %s больш" + +#: kallithea/lib/helpers.py:720 +#: kallithea/templates/changelog/changelog.html:44 +msgid "revisions" +msgstr "версіі" + +#: kallithea/lib/helpers.py:744 +#, python-format +msgid "fork name %s" +msgstr "імя форка %s" + +#: kallithea/lib/helpers.py:761 +#, python-format +msgid "Pull request #%s" +msgstr "Pull-запыт #%s" + +#: kallithea/lib/helpers.py:771 +msgid "[deleted] repository" +msgstr "[выдалены] рэпазітар" + +#: kallithea/lib/helpers.py:773 kallithea/lib/helpers.py:785 +msgid "[created] repository" +msgstr "[створаны] рэпазітар" + +#: kallithea/lib/helpers.py:775 +msgid "[created] repository as fork" +msgstr "[створаны] рэпазітар як форк" + +#: kallithea/lib/helpers.py:777 kallithea/lib/helpers.py:787 +msgid "[forked] repository" +msgstr "[форкнуты] рэпазітар" + +#: kallithea/lib/helpers.py:779 kallithea/lib/helpers.py:789 +msgid "[updated] repository" +msgstr "[абноўлены] рэпазітар" + +#: kallithea/lib/helpers.py:781 +msgid "[downloaded] archive from repository" +msgstr "[загружаны] архіў з рэпазітара" + +#: kallithea/lib/helpers.py:783 +msgid "[delete] repository" +msgstr "[выдалены] рэпазітар" + +#: kallithea/lib/helpers.py:791 +msgid "[created] user" +msgstr "[створаны] карыстач" + +#: kallithea/lib/helpers.py:793 +msgid "[updated] user" +msgstr "[абноўлены] карыстач" + +#: kallithea/lib/helpers.py:795 +msgid "[created] user group" +msgstr "[створана] група карыстачоў" + +#: kallithea/lib/helpers.py:797 +msgid "[updated] user group" +msgstr "[абноўлена] група карыстачоў" + +#: kallithea/lib/helpers.py:799 +msgid "[commented] on revision in repository" +msgstr "[каментар] да рэвізіі ў рэпазітары" + +#: kallithea/lib/helpers.py:801 +msgid "[commented] on pull request for" +msgstr "[пракаменціравана] у запыце на занясенне змен для" + +#: kallithea/lib/helpers.py:803 +msgid "[closed] pull request for" +msgstr "[зачынены] Pull-запыт для" + +#: kallithea/lib/helpers.py:805 +msgid "[pushed] into" +msgstr "[адпраўлена] у" + +#: kallithea/lib/helpers.py:807 +msgid "[committed via Kallithea] into repository" +msgstr "[занесены змены з дапамогай Kallithea] у рэпазітары" + +#: kallithea/lib/helpers.py:809 +msgid "[pulled from remote] into repository" +msgstr "[занесены змены з выдаленага рэпазітара] у рэпазітар" + +#: kallithea/lib/helpers.py:811 +msgid "[pulled] from" +msgstr "[занесены змены] з" + +#: kallithea/lib/helpers.py:813 +msgid "[started following] repository" +msgstr "[дададзены ў назіранні] рэпазітар" + +#: kallithea/lib/helpers.py:815 +msgid "[stopped following] repository" +msgstr "[выдалены з назірання] рэпазітар" + +#: kallithea/lib/helpers.py:1144 +#, python-format +msgid " and %s more" +msgstr " і на %s больш" + +#: kallithea/lib/helpers.py:1148 +msgid "No Files" +msgstr "Файлаў няма" + +#: kallithea/lib/helpers.py:1214 +msgid "new file" +msgstr "новы файл" + +#: kallithea/lib/helpers.py:1217 +msgid "mod" +msgstr "зменены" + +#: kallithea/lib/helpers.py:1220 +msgid "del" +msgstr "выдалены" + +#: kallithea/lib/helpers.py:1223 +msgid "rename" +msgstr "пераназваны" + +#: kallithea/lib/helpers.py:1228 +msgid "chmod" +msgstr "chmod" + +#: kallithea/lib/helpers.py:1460 +#, 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 адсутнічае ў базе дадзеных; магчыма, ён быў створаны ці " +"пераназваны з файлавай сістэмы. Калі ласка, перазапусціце прыкладанне для " +"сканавання рэпазітароў" + +#: kallithea/lib/utils2.py:425 +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d год" +msgstr[1] "%d гадоў" +msgstr[2] "%d гады" + +#: kallithea/lib/utils2.py:426 +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d месяц" +msgstr[1] "%d месяца" +msgstr[2] "%d месяцаў" + +#: kallithea/lib/utils2.py:427 +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d дзень" +msgstr[1] "%d дня" +msgstr[2] "%d дзён" + +#: kallithea/lib/utils2.py:428 +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d гадзіна" +msgstr[1] "%d гадзін" +msgstr[2] "%d гадзіны" + +#: kallithea/lib/utils2.py:429 +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d хвіліна" +msgstr[1] "%d мінуць" +msgstr[2] "%d хвіліны" + +#: kallithea/lib/utils2.py:430 +#, python-format +msgid "%d second" +msgid_plural "%d seconds" +msgstr[0] "%d секунды" +msgstr[1] "%d секунды" +msgstr[2] "%d секунды" + +#: kallithea/lib/utils2.py:446 +#, python-format +msgid "in %s" +msgstr "у %s" + +#: kallithea/lib/utils2.py:448 +#, python-format +msgid "%s ago" +msgstr "%s назад" + +#: kallithea/lib/utils2.py:450 +#, python-format +msgid "in %s and %s" +msgstr "у %s і %s" + +#: kallithea/lib/utils2.py:453 +#, python-format +msgid "%s and %s ago" +msgstr "%s і %s назад" + +#: kallithea/lib/utils2.py:456 +msgid "just now" +msgstr "прама цяпер" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1163 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1182 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1303 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1388 +#: 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:1651 +msgid "Repository no access" +msgstr "Рэпазітар - няма доступу" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1164 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1183 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1304 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1389 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1409 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1455 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1512 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1513 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1573 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1623 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1650 kallithea/model/db.py:1652 +msgid "Repository read access" +msgstr "Рэпазітар - доступ на чытанне" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1165 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1184 +#: 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:1653 +msgid "Repository write access" +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: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:1654 +msgid "Repository admin access" +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:1308 +msgid "Repository Group no access" +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:1309 +msgid "Repository Group read access" +msgstr "Група Рэпазітароў - доступ на чытанне" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1170 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1189 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1310 +msgid "Repository Group write access" +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:1311 +msgid "Repository Group admin access" +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:1313 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1398 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1406 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1452 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1509 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1510 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1570 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1620 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1647 kallithea/model/db.py:1649 +msgid "Kallithea Administrator" +msgstr "Адміністратар Kallithea" + +#: 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:1314 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1399 +#: 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:1672 +msgid "Repository creation disabled" +msgstr "Стварэнне рэпазітароў адключана" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1175 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1194 +#: 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:1430 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1476 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1533 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1534 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1555 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1594 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1644 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1671 kallithea/model/db.py:1673 +msgid "Repository creation enabled" +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:1316 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1401 +#: 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:1648 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1675 kallithea/model/db.py:1677 +msgid "Repository forking disabled" +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:1317 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1402 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1433 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1479 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1536 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1537 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1558 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1597 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1649 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1676 kallithea/model/db.py:1678 +msgid "Repository forking enabled" +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:1318 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1403 +msgid "Register disabled" +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:1319 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1404 +msgid "Register new user with Kallithea with manual activation" +msgstr "Рэгістрацыя новага карыстача ў Kallithea з ручной актывацыяй" + +#: 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:1322 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1407 +msgid "Register new user with Kallithea with auto activation" +msgstr "Рэгістрацыя новага карыстача ў Kallithea з аўтаматычнай актывацыяй" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1623 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1650 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1763 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1838 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1934 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1980 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2040 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2041 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2062 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2101 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2154 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2200 kallithea/model/db.py:2202 +msgid "Not Reviewed" +msgstr "Не прагледжана" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1624 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1651 +#: kallithea/lib/dbmigrate/schema/db_1_5_2.py:1764 +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1839 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1935 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1981 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:2041 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:2042 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:2063 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:2102 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:2155 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:2201 kallithea/model/db.py:2203 +msgid "Approved" +msgstr "Ухвалена" + +#: kallithea/lib/dbmigrate/schema/db_1_4_0.py:1625 +#: kallithea/lib/dbmigrate/schema/db_1_5_0.py:1652 +#: 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:2204 +msgid "Rejected" +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: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:2205 +msgid "Under Review" +msgstr "На разглядзе" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1252 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1270 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1300 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1357 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1358 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1379 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1418 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1471 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1498 kallithea/model/db.py:1500 +msgid "top level" +msgstr "верхні ўзровень" + +#: 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:1656 +msgid "Repository group no access" +msgstr "Група Рэпазітароў - няма доступу" + +#: kallithea/lib/dbmigrate/schema/db_1_6_0.py:1394 +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1414 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1460 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1517 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1518 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1578 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1628 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1655 kallithea/model/db.py:1657 +msgid "Repository group read access" +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:1658 +msgid "Repository group write 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:1659 +msgid "Repository group admin access" +msgstr "Група рэпазітароў - адміністраванне" + +#: 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:1661 +msgid "User group no access" +msgstr "Група карыстачоў - няма доступу" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1419 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1465 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1522 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1523 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1544 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1583 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1633 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1660 kallithea/model/db.py:1662 +msgid "User group read 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:1663 +msgid "User group write 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:1664 +msgid "User group admin 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:1666 +msgid "Repository Group creation disabled" +msgstr "Стварэнне груп рэпазітароў адключана" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1424 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1470 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1527 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1528 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1549 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1588 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1638 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1665 kallithea/model/db.py:1667 +msgid "Repository Group creation enabled" +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:1669 +msgid "User Group creation disabled" +msgstr "Стварэнне груп карыстачоў адключана" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1427 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1473 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1530 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1531 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1552 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1591 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1641 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1668 kallithea/model/db.py:1670 +msgid "User Group creation enabled" +msgstr "Стварэнне груп карыстачоў уключана" + +#: 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:1680 +msgid "Registration disabled" +msgstr "Рэгістрацыя адключана" + +#: kallithea/lib/dbmigrate/schema/db_1_7_0.py:1436 +#: kallithea/lib/dbmigrate/schema/db_1_8_0.py:1482 +#: kallithea/lib/dbmigrate/schema/db_2_0_0.py:1539 +#: kallithea/lib/dbmigrate/schema/db_2_0_1.py:1540 +#: kallithea/lib/dbmigrate/schema/db_2_0_2.py:1561 +#: kallithea/lib/dbmigrate/schema/db_2_1_0.py:1600 +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1652 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1679 kallithea/model/db.py:1681 +msgid "User Registration with manual account activation" +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:1682 +msgid "User Registration with automatic account activation" +msgstr "Рэгістрацыя карыстача з аўтаматычнай актывацыяй" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1645 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1672 kallithea/model/db.py:1674 +msgid "Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/lib/dbmigrate/schema/db_2_2_0.py:1646 +#: kallithea/lib/dbmigrate/schema/db_2_2_3.py:1673 kallithea/model/db.py:1675 +msgid "" +"Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/comment.py:76 +#, python-format +msgid "on line %s" +msgstr "на радку %s" + +#: kallithea/model/comment.py:231 kallithea/model/pull_request.py:164 +msgid "[Mention]" +msgstr "[Згадванне]" + +#: kallithea/model/forms.py:57 +msgid "Please enter a login" +msgstr "Калі ласка, увядзіце лагін" + +#: kallithea/model/forms.py:58 +#, python-format +msgid "Enter a value %(min)i characters long or more" +msgstr "Увядзіце значэнне даўжынёй не меней %(min)i знакаў" + +#: kallithea/model/forms.py:66 +msgid "Please enter a password" +msgstr "Калі ласка, увядзіце пароль" + +#: kallithea/model/forms.py:67 +#, python-format +msgid "Enter %(min)i characters or more" +msgstr "Увядзіце не меней %(min)i знакаў" + +#: kallithea/model/forms.py:156 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:252 +#, python-format +msgid "%(user)s commented on changeset at %(when)s" +msgstr "%(user)s пакінуў каментар да набору змен %(when)s" + +#: kallithea/model/notification.py:253 +#, python-format +msgid "%(user)s sent message at %(when)s" +msgstr "%(user)s адправіў паведамленне %(when)s" + +#: kallithea/model/notification.py:254 +#, python-format +msgid "%(user)s mentioned you at %(when)s" +msgstr "%(user)s згадаў вас %(when)s" + +#: kallithea/model/notification.py:255 +#, python-format +msgid "%(user)s registered in Kallithea at %(when)s" +msgstr "%(user)s зарэгістраваўся ў Kallithea %(when)s" + +#: kallithea/model/notification.py:256 +#, python-format +msgid "%(user)s opened new pull request at %(when)s" +msgstr "%(user)s адкрыў новы pull-запыт %(when)s" + +#: kallithea/model/notification.py:257 +#, python-format +msgid "%(user)s commented on pull request at %(when)s" +msgstr "%(user)s пакінуў каментар да pull-запыту %(when)s" + +#: kallithea/model/notification.py:296 +#, python-format +msgid "" +"Comment on %(repo_name)s changeset %(short_id)s on %(branch)s by " +"%(comment_username)s" +msgstr "" + +#: kallithea/model/notification.py:299 +#, python-format +msgid "New user %(new_username)s registered" +msgstr "Новы карыстач \"%(new_username)s\" зарэгістраваны" + +#: kallithea/model/notification.py:301 +#, python-format +msgid "" +"Review request on %(repo_name)s pull request #%(pr_id)s from %(ref)s by " +"%(pr_username)s" +msgstr "" + +#: kallithea/model/notification.py:302 +#, python-format +msgid "" +"Comment on %(repo_name)s pull request #%(pr_id)s from %(ref)s by " +"%(comment_username)s" +msgstr "" + +#: kallithea/model/notification.py:315 +msgid "Closing" +msgstr "Зачынены" + +#: kallithea/model/pull_request.py:132 +#, 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" + +#: kallithea/model/scm.py:808 +msgid "latest tip" +msgstr "апошняя версія" + +#: kallithea/model/user.py:194 +msgid "New user registration" +msgstr "Рэгістрацыя новага карыстача" + +#: kallithea/model/user.py:214 kallithea/model/user.py:236 +msgid "You can't Edit this user since it's crucial for entire application" +msgstr "" +"Вы не можаце рэдагаваць карыстача, паколькі гэта крытычна для працы ўсяго " +"прыкладання" + +#: kallithea/model/user.py:255 +msgid "You can't remove this user since it's crucial for entire application" +msgstr "" +"Вы не можаце выдаліць карыстача, паколькі гэта крытычна для працы ўсяго " +"прыкладання" + +#: kallithea/model/user.py:261 +#, python-format +msgid "" +"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:268 +#, python-format +msgid "" +"User \"%s\" still owns %s repository groups and cannot be removed. Switch " +"owners or remove those repository groups: %s" +msgstr "" +"Карыстач \"%s\" усё яшчэ з'яўляецца ўладальнікам %s груп рэпазітароў і таму " +"не можа быць выдалены. Зменіце ўладальніка ці выдаліце дадзеныя групы: %s" + +#: kallithea/model/user.py:275 +#, python-format +msgid "" +"User \"%s\" still owns %s user groups and cannot be removed. Switch owners " +"or remove those user groups: %s" +msgstr "" +"Карыстач \"%s\" усё яшчэ з'яўляецца ўладальнікам %s груп карыстачоў і таму " +"не можа быць выдалены. Зменіце ўладальніка ці выдаліце дадзеныя групы: %s" + +#: kallithea/model/user.py:305 +msgid "Password reset link" +msgstr "Спасылка скіду пароля" + +#: kallithea/model/user.py:328 +msgid "Your new password" +msgstr "Ваш новы пароль" + +#: kallithea/model/user.py:329 +#, python-format +msgid "Your new Kallithea password:%s" +msgstr "Ваш новы пароль ад Kallithea: %s" + +#: kallithea/model/validators.py:83 kallithea/model/validators.py:84 +msgid "Value cannot be an empty list" +msgstr "Значэнне не можа быць пустым спісам" + +#: kallithea/model/validators.py:101 +#, python-format +msgid "Username \"%(username)s\" already exists" +msgstr "Карыстач з імем \"%(username)s\" ужо існуе" + +#: kallithea/model/validators.py:103 +#, python-format +msgid "Username \"%(username)s\" is forbidden" +msgstr "Імя \"%(username)s\" адхілена" + +#: kallithea/model/validators.py:105 +msgid "" +"Username may only contain alphanumeric characters underscores, periods or " +"dashes and must begin with alphanumeric character or underscore" +msgstr "" +"Імя карыстача можа ўтрымоўваць толькі літары, лічбы, знакі падкрэслення, " +"кропкі і працяжнік; а гэтак жа павінна пачынацца з літары, лічбы або са " +"знака падкрэслення" + +#: kallithea/model/validators.py:132 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:139 +#, python-format +msgid "Username %(username)s is not valid" +msgstr "Імя \"%(username)s\" недапушчальна" + +#: kallithea/model/validators.py:158 +msgid "Invalid user group name" +msgstr "Няслушнае імя групы карыстачоў" + +#: kallithea/model/validators.py:159 +#, python-format +msgid "User group \"%(usergroup)s\" already exists" +msgstr "Група карыстачоў \"%(usergroup)s\" ужо існуе" + +#: kallithea/model/validators.py:161 +msgid "" +"user group name may only contain alphanumeric characters underscores, " +"periods or dashes and must begin with alphanumeric character" +msgstr "" +"імя групы карыстачоў можа ўтрымоўваць толькі літары, лічбы, знакі " +"падкрэслення, кропкі і працяжнік; а гэтак жа павінна пачынацца з літары ці " +"лічбы" + +#: kallithea/model/validators.py:199 +msgid "Cannot assign this group as parent" +msgstr "Немагчыма выкарыстоўваць гэту групу як бацькі" + +#: kallithea/model/validators.py:200 +#, python-format +msgid "Group \"%(group_name)s\" already exists" +msgstr "Група \"%(group_name)s\" ужо існуе" + +#: kallithea/model/validators.py:202 +#, python-format +msgid "Repository with name \"%(group_name)s\" already exists" +msgstr "Рэпазітар з імем \"%(group_name)s\" ужо існуе" + +#: kallithea/model/validators.py:260 +msgid "Invalid characters (non-ascii) in password" +msgstr "Недапушчальныя знакі (не ascii) у паролі" + +#: kallithea/model/validators.py:275 +msgid "Invalid old password" +msgstr "Няслушна зададзены стары пароль" + +#: kallithea/model/validators.py:291 +msgid "Passwords do not match" +msgstr "Паролі не супадаюць" + +#: kallithea/model/validators.py:308 +msgid "invalid password" +msgstr "няслушны пароль" + +#: kallithea/model/validators.py:309 +msgid "invalid user name" +msgstr "няслушнае імя карыстача" + +#: kallithea/model/validators.py:310 +msgid "Your account is disabled" +msgstr "Ваш акаўнт выключаны" + +#: kallithea/model/validators.py:354 +#, python-format +msgid "Repository name %(repo)s is disallowed" +msgstr "Імя рэпазітара %(repo)s забаронена" + +#: kallithea/model/validators.py:356 +#, python-format +msgid "Repository named %(repo)s already exists" +msgstr "Рэпазітар %(repo)s ужо існуе" + +#: kallithea/model/validators.py:357 +#, python-format +msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" +msgstr "Рэпазітар \"%(repo)s\" ужо існуе ў групе \"%(group)s\"" + +#: kallithea/model/validators.py:359 +#, python-format +msgid "Repository group with name \"%(repo)s\" already exists" +msgstr "Група рэпазітароў \"%(repo)s\" ужо існуе" + +#: kallithea/model/validators.py:474 +msgid "invalid clone URL" +msgstr "няслушны URL для кланавання" + +#: kallithea/model/validators.py:475 +msgid "Invalid clone URL, provide a valid clone http(s)/svn+http(s)/ssh URL" +msgstr "" +"Няслушны URL кланаванні, падайце карэктны URL для кланавання ў фармаце " +"http(s)/svn+http(s)/ssh" + +#: kallithea/model/validators.py:500 +msgid "Fork has to be the same type as parent" +msgstr "Тып форка будзе супадаць з бацькоўскім" + +#: kallithea/model/validators.py:515 +msgid "You don't have permissions to create repository in this group" +msgstr "У вас недастаткова мае рацыю для стварэння рэпазітароў у гэтай групе" + +#: kallithea/model/validators.py:517 +msgid "no permission to create repository in root location" +msgstr "недастаткова мае рацыю для стварэння рэпазітара ў каранёвым каталогу" + +#: kallithea/model/validators.py:566 +msgid "You don't have permissions to create a group in this location" +msgstr "У Вас недастаткова прывілеяў для стварэння групы ў гэтым месцы" + +#: kallithea/model/validators.py:607 +msgid "This username or user group name is not valid" +msgstr "Дадзенае імя карыстача ці групы карыстачоў недапушчальна" + +#: kallithea/model/validators.py:700 +msgid "This is not a valid path" +msgstr "Гэты шлях хібны" + +#: kallithea/model/validators.py:715 +msgid "This e-mail address is already taken" +msgstr "Гэты E-mail ужо заняты" + +#: kallithea/model/validators.py:735 +#, python-format +msgid "e-mail \"%(email)s\" does not exist." +msgstr "\"%(email)s\" не існуе." + +#: kallithea/model/validators.py:772 +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 - гэта " +"эквівалент імя карыстача" + +#: kallithea/model/validators.py:785 +#, python-format +msgid "Revisions %(revs)s are already part of pull request or have set status" +msgstr "Рэвізіі %(revs)s ужо ўключаны ў pull-request ці маюць усталяваны статус" + +#: kallithea/model/validators.py:817 +msgid "Please enter a valid IPv4 or IpV6 address" +msgstr "Калі ласка, увядзіце існы IPv4 ці IpV6 адрас" + +#: kallithea/model/validators.py:818 +#, 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:851 +msgid "Key name can only consist of letters, underscore, dash or numbers" +msgstr "" +"Ключавое імя можа толькі складацца з літар, знака падкрэслення, працяжнік ці " +"лікаў" + +#: kallithea/model/validators.py:865 +msgid "Filename cannot be inside a directory" +msgstr "Файла няма ў каталогу" + +#: kallithea/model/validators.py:881 +#, 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:17 +msgid "About" +msgstr "Пра праграму" + +#: kallithea/templates/index.html:5 +msgid "Dashboard" +msgstr "Панэль кіравання" + +#: 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:9 +#: kallithea/templates/admin/repos/repos.html:9 +#: kallithea/templates/admin/user_groups/user_groups.html:9 +#: kallithea/templates/admin/users/users.html:9 +#: kallithea/templates/bookmarks/bookmarks.html:9 +#: kallithea/templates/branches/branches.html:9 +#: kallithea/templates/journal/journal.html:9 +#: kallithea/templates/journal/journal.html:48 +#: kallithea/templates/journal/journal.html:49 +#: kallithea/templates/tags/tags.html:9 +msgid "quick filter..." +msgstr "фільтр..." + +#: kallithea/templates/index_base.html:6 +msgid "repositories" +msgstr "рэпазітары" + +#: kallithea/templates/index_base.html:20 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/admin/repos/repo_add.html:5 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/repos/repos.html:22 +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:5 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:13 +#: kallithea/templates/admin/repo_groups/repo_groups.html:26 +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:131 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:64 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:42 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:17 +#: kallithea/templates/admin/repo_groups/repo_groups.html:47 +#: kallithea/templates/admin/repos/repo_add_base.html:32 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +#: kallithea/templates/admin/repos/repos.html:48 +#: kallithea/templates/admin/user_groups/user_group_add.html:40 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:15 +#: kallithea/templates/admin/user_groups/user_groups.html:47 +#: kallithea/templates/admin/users/user_edit_api_keys.html:64 +#: kallithea/templates/email_templates/changeset_comment.html:18 +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/forks/fork.html:38 +#: kallithea/templates/pullrequests/pullrequest.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:38 +#: kallithea/templates/pullrequests/pullrequest_show.html:63 +#: kallithea/templates/summary/summary.html:84 +msgid "Description" +msgstr "Апісанне" + +#: kallithea/templates/index_base.html:129 +#: 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:46 +#: kallithea/templates/admin/repos/repo_add_base.html:9 +#: kallithea/templates/admin/repos/repo_edit_settings.html:7 +#: kallithea/templates/admin/repos/repos.html:47 +#: kallithea/templates/admin/user_groups/user_groups.html:46 +#: kallithea/templates/base/perms_summary.html:53 +#: kallithea/templates/bookmarks/bookmarks.html:49 +#: kallithea/templates/bookmarks/bookmarks_data.html:7 +#: kallithea/templates/branches/branches.html:49 +#: kallithea/templates/branches/branches_data.html:7 +#: kallithea/templates/files/files_browser.html:60 +#: kallithea/templates/journal/journal.html:187 +#: kallithea/templates/journal/journal.html:278 +#: kallithea/templates/tags/tags.html:49 +#: kallithea/templates/tags/tags_data.html:7 +msgid "Name" +msgstr "Імя" + +#: kallithea/templates/index_base.html:132 +msgid "Last Change" +msgstr "Апошняя змена" + +#: kallithea/templates/index_base.html:134 +#: 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:49 +#: kallithea/templates/journal/journal.html:189 +#: kallithea/templates/journal/journal.html:280 +msgid "Tip" +msgstr "Стан" + +#: kallithea/templates/index_base.html:136 +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:49 +#: kallithea/templates/admin/repos/repo_edit_settings.html:60 +#: kallithea/templates/admin/repos/repos.html:50 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:50 +#: kallithea/templates/summary/summary.html:137 +msgid "Owner" +msgstr "Уладальнік" + +#: kallithea/templates/index_base.html:144 +#: 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:44 +#: kallithea/templates/bookmarks/bookmarks.html:79 +#: kallithea/templates/branches/branches.html:79 +#: kallithea/templates/journal/journal.html:198 +#: kallithea/templates/journal/journal.html:289 +#: kallithea/templates/tags/tags.html:79 +msgid "Click to sort ascending" +msgstr "Па ўзрастанні" + +#: kallithea/templates/index_base.html:145 +#: 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:45 +#: kallithea/templates/bookmarks/bookmarks.html:80 +#: kallithea/templates/branches/branches.html:80 +#: kallithea/templates/journal/journal.html:199 +#: kallithea/templates/journal/journal.html:290 +#: kallithea/templates/tags/tags.html:80 +msgid "Click to sort descending" +msgstr "Па змяншэнні" + +#: kallithea/templates/index_base.html:146 +msgid "No repositories found." +msgstr "Рэпазітары не знойдзены." + +#: kallithea/templates/index_base.html:147 +#: 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:47 +#: kallithea/templates/bookmarks/bookmarks.html:82 +#: kallithea/templates/branches/branches.html:82 +#: kallithea/templates/journal/journal.html:201 +#: kallithea/templates/journal/journal.html:292 +#: kallithea/templates/tags/tags.html:82 +msgid "Data error." +msgstr "Памылка дадзеных." + +#: kallithea/templates/index_base.html:148 +#: 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:143 +#: kallithea/templates/base/root.html:48 +#: kallithea/templates/bookmarks/bookmarks.html:83 +#: kallithea/templates/branches/branches.html:83 +#: kallithea/templates/journal/journal.html:202 +#: kallithea/templates/journal/journal.html:293 +#: kallithea/templates/tags/tags.html:83 +msgid "Loading..." +msgstr "Загрузка..." + +#: kallithea/templates/login.html:5 kallithea/templates/login.html:15 +#: kallithea/templates/base/base.html:329 +msgid "Log In" +msgstr "Увайсці" + +#: kallithea/templates/login.html:13 +#, python-format +msgid "Log In to %s" +msgstr "Увайсці ў %s" + +#: kallithea/templates/login.html:27 kallithea/templates/register.html:24 +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:32 +#: kallithea/templates/admin/users/user_add.html:32 +#: kallithea/templates/admin/users/user_edit_profile.html:33 +#: kallithea/templates/admin/users/users.html:50 +#: kallithea/templates/base/base.html:305 +msgid "Username" +msgstr "Імя карыстача" + +#: kallithea/templates/login.html:36 kallithea/templates/register.html:33 +#: kallithea/templates/admin/my_account/my_account.html:36 +#: kallithea/templates/admin/users/user_add.html:41 +#: kallithea/templates/base/base.html:314 +msgid "Password" +msgstr "Пароль" + +#: kallithea/templates/login.html:46 +msgid "Remember me" +msgstr "Запомніць" + +#: kallithea/templates/login.html:50 +msgid "Sign In" +msgstr "Увайсці" + +#: kallithea/templates/login.html:56 +msgid "Forgot your password ?" +msgstr "Забыліся пароль?" + +#: kallithea/templates/login.html:59 kallithea/templates/base/base.html:325 +msgid "Don't have an account ?" +msgstr "Няма акаўнта?" + +#: kallithea/templates/password_reset.html:5 +msgid "Password Reset" +msgstr "Скід пароля" + +#: kallithea/templates/password_reset.html:12 +#, python-format +msgid "Reset Your Password to %s" +msgstr "Забыліся пароль для %s?" + +#: kallithea/templates/password_reset.html:14 +msgid "Reset Your Password" +msgstr "Забыліся пароль?" + +#: kallithea/templates/password_reset.html:25 +msgid "Email Address" +msgstr "Паштовы адрас" + +#: kallithea/templates/password_reset.html:35 +#: kallithea/templates/register.html:79 +msgid "Captcha" +msgstr "Капча" + +#: kallithea/templates/password_reset.html:46 +msgid "Send Password Reset Email" +msgstr "Паслаць спасылку скіду пароля" + +#: kallithea/templates/password_reset.html:47 +msgid "" +"Password reset link will be sent to the email address matching your username." +msgstr "Спасылка для скіду пароля была адпраўлена на адпаведны e-mail." + +#: kallithea/templates/register.html:5 kallithea/templates/register.html:14 +#: kallithea/templates/register.html:90 +msgid "Sign Up" +msgstr "Рэгістрацыя" + +#: kallithea/templates/register.html:12 +#, python-format +msgid "Sign Up to %s" +msgstr "Рэгістра на %s" + +#: kallithea/templates/register.html:42 +msgid "Re-enter password" +msgstr "Паўторыце пароль" + +#: kallithea/templates/register.html:51 +#: kallithea/templates/admin/my_account/my_account_profile.html:43 +#: kallithea/templates/admin/users/user_add.html:59 +#: kallithea/templates/admin/users/user_edit_profile.html:87 +#: kallithea/templates/admin/users/users.html:51 +msgid "First Name" +msgstr "Імя" + +#: kallithea/templates/register.html:60 +#: kallithea/templates/admin/my_account/my_account_profile.html:52 +#: kallithea/templates/admin/users/user_add.html:68 +#: kallithea/templates/admin/users/user_edit_profile.html:96 +#: kallithea/templates/admin/users/users.html:52 +msgid "Last Name" +msgstr "Прозвішча" + +#: kallithea/templates/register.html:69 +#: kallithea/templates/admin/my_account/my_account_profile.html:61 +#: kallithea/templates/admin/settings/settings.html:31 +#: kallithea/templates/admin/users/user_add.html:77 +#: kallithea/templates/admin/users/user_edit_profile.html:42 +msgid "Email" +msgstr "E-mail" + +#: kallithea/templates/register.html:92 +msgid "Registered accounts are ready to use and need no further action." +msgstr "" + +#: kallithea/templates/register.html:94 +msgid "Please wait for an administrator to activate your account." +msgstr "" +"Калі ласка, пачакайце, пакуль адміністратар пацвердзіць Вашу рэгістрацыю." + +#: kallithea/templates/switch_to_list.html:10 +#: kallithea/templates/branches/branches_data.html:69 +msgid "There are no branches yet" +msgstr "Галінкі яшчэ не створаны" + +#: 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 "Пазнакі адсутнічаюць" + +#: kallithea/templates/switch_to_list.html:45 +#: kallithea/templates/bookmarks/bookmarks_data.html:43 +msgid "There are no bookmarks yet" +msgstr "Закладак яшчэ няма" + +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:13 +#: kallithea/templates/base/base.html:59 +msgid "Admin Journal" +msgstr "Часопіс адміністратара" + +#: kallithea/templates/admin/admin.html:10 +msgid "journal filter..." +msgstr "Фільтр часопіса..." + +#: kallithea/templates/admin/admin.html:12 +#: kallithea/templates/journal/journal.html:11 +msgid "Filter" +msgstr "Адфільтраваць" + +#: kallithea/templates/admin/admin.html:13 +#: kallithea/templates/journal/journal.html:12 +#, python-format +msgid "%s Entry" +msgid_plural "%s Entries" +msgstr[0] "%s запіс" +msgstr[1] "%s запісаў" +msgstr[2] "%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:50 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +#: kallithea/templates/admin/repos/repos.html:52 +#: kallithea/templates/admin/user_groups/user_groups.html:51 +#: kallithea/templates/admin/users/users.html:57 +#: kallithea/templates/journal/journal.html:191 +#: kallithea/templates/journal/journal.html:282 +msgid "Action" +msgstr "Дзеянне" + +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:18 +msgid "Repository" +msgstr "Рэпазітар" + +#: kallithea/templates/admin/admin_log.html:8 +#: kallithea/templates/bookmarks/bookmarks.html:51 +#: kallithea/templates/bookmarks/bookmarks_data.html:9 +#: kallithea/templates/branches/branches.html:51 +#: kallithea/templates/branches/branches_data.html:9 +#: kallithea/templates/tags/tags.html:51 +#: kallithea/templates/tags/tags_data.html:9 +msgid "Date" +msgstr "Дата" + +#: kallithea/templates/admin/admin_log.html:9 +msgid "From IP" +msgstr "З IP" + +#: kallithea/templates/admin/admin_log.html:63 +msgid "No actions yet" +msgstr "Дзеянні яшчэ не вырабляліся" + +#: kallithea/templates/admin/auth/auth_settings.html:5 +msgid "Authentication Settings" +msgstr "Налады аўтэнтыфікацыі" + +#: kallithea/templates/admin/auth/auth_settings.html:11 +#: kallithea/templates/base/base.html:65 +msgid "Authentication" +msgstr "Аўтэнтыфікацыя" + +#: kallithea/templates/admin/auth/auth_settings.html:28 +msgid "Authentication Plugins" +msgstr "Убудовы аўтэнтыфікацыі" + +#: kallithea/templates/admin/auth/auth_settings.html:31 +msgid "Enabled Plugins" +msgstr "Уключаныя ўбудовы" + +#: kallithea/templates/admin/auth/auth_settings.html:33 +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:34 +msgid "Available built-in plugins" +msgstr "Даступныя ўбудаваныя ўбудовы" + +#: kallithea/templates/admin/auth/auth_settings.html:40 +#: kallithea/templates/base/root.html:40 +msgid "enabled" +msgstr "уключана" + +#: kallithea/templates/admin/auth/auth_settings.html:40 +#: kallithea/templates/base/root.html:41 +msgid "disabled" +msgstr "адключана" + +#: kallithea/templates/admin/auth/auth_settings.html:51 +msgid "Plugin" +msgstr "Убудова" + +#: kallithea/templates/admin/auth/auth_settings.html:101 +#: kallithea/templates/admin/defaults/defaults.html:84 +#: kallithea/templates/admin/my_account/my_account_password.html:33 +#: kallithea/templates/admin/my_account/my_account_profile.html:70 +#: kallithea/templates/admin/permissions/permissions_globals.html:108 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:69 +#: 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:57 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:104 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:60 +#: kallithea/templates/admin/users/user_add.html:96 +#: kallithea/templates/admin/users/user_edit_profile.html:122 +#: kallithea/templates/base/default_perms_box.html:64 +msgid "Save" +msgstr "Захаваць" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:25 +msgid "Repository Defaults" +msgstr "Значэнні па змаўчанні" + +#: kallithea/templates/admin/defaults/defaults.html:11 +#: kallithea/templates/base/base.html:66 +msgid "Defaults" +msgstr "Значэнні па змаўчанні" + +#: kallithea/templates/admin/defaults/defaults.html:35 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 +msgid "Type" +msgstr "Тып" + +#: kallithea/templates/admin/defaults/defaults.html:44 +#: 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:74 +msgid "Private repository" +msgstr "Прыватны рэпазітар" + +#: kallithea/templates/admin/defaults/defaults.html:48 +#: kallithea/templates/admin/repos/repo_add_base.html:81 +#: kallithea/templates/admin/repos/repo_edit_settings.html:86 +#: kallithea/templates/forks/fork.html:72 +msgid "" +"Private repositories are only visible to people explicitly added as " +"collaborators." +msgstr "Прыватныя рэпазітары бачныя толькі іх удзельнікам." + +#: kallithea/templates/admin/defaults/defaults.html:55 +#: kallithea/templates/admin/repos/repo_edit_settings.html:91 +msgid "Enable statistics" +msgstr "Уключыць статыстыку" + +#: kallithea/templates/admin/defaults/defaults.html:59 +#: kallithea/templates/admin/repos/repo_edit_settings.html:95 +msgid "Enable statistics window on summary page." +msgstr "Уключыць акно статыстыкі на старонцы «Агульныя звесткі»." + +#: kallithea/templates/admin/defaults/defaults.html:65 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 +msgid "Enable downloads" +msgstr "Уключыць спампоўку" + +#: kallithea/templates/admin/defaults/defaults.html:69 +#: kallithea/templates/admin/repos/repo_edit_settings.html:104 +msgid "Enable download menu on summary page." +msgstr "Уключыць меню спампоўкі на старонцы «Агульныя звесткі»." + +#: kallithea/templates/admin/defaults/defaults.html:75 +#: 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:79 +#: 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:18 +msgid "Edit Gist" +msgstr "Праўка gist-запісы" + +#: kallithea/templates/admin/gists/edit.html:36 +#, 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:55 +#: kallithea/templates/admin/gists/new.html:39 +msgid "Gist description ..." +msgstr "Апісанне..." + +#: kallithea/templates/admin/gists/edit.html:57 +#: kallithea/templates/admin/gists/new.html:41 +msgid "Gist lifetime" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/edit.html:63 +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/admin/gists/index.html:59 +#: kallithea/templates/admin/gists/show.html:47 +#: kallithea/templates/admin/gists/show.html:49 +msgid "Expires" +msgstr "Мінае" + +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/index.html:57 +#: kallithea/templates/admin/gists/show.html:47 +#: 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:145 +msgid "Update Gist" +msgstr "Абнавіць" + +#: kallithea/templates/admin/gists/edit.html:146 +#: kallithea/templates/changeset/changeset_file_comment.html:89 +msgid "Cancel" +msgstr "Адмена" + +#: kallithea/templates/admin/gists/index.html:6 +#: kallithea/templates/admin/gists/index.html:16 +#, python-format +msgid "Private Gists for User %s" +msgstr "Прыватная gist-запіс для карыстача %s" + +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:18 +#, python-format +msgid "Public Gists for User %s" +msgstr "Публічная gist-запіс для карыстача %s" + +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:20 +msgid "Public Gists" +msgstr "Публічныя gist-запісы" + +#: kallithea/templates/admin/gists/index.html:37 +#: kallithea/templates/admin/gists/show.html:25 +#: kallithea/templates/base/base.html:240 +msgid "Create New Gist" +msgstr "Стварыць новую gist-запіс" + +#: kallithea/templates/admin/gists/index.html:54 +#: kallithea/templates/data_table/_dt_elements.html:143 +msgid "Created" +msgstr "Створана" + +#: kallithea/templates/admin/gists/index.html:74 +msgid "There are no gists yet" +msgstr "Gist-запісы адсутнічаюць" + +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:18 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:47 +msgid "name this file..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:56 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:57 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:58 +#: 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:71 +#: 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:57 +#: kallithea/templates/admin/settings/settings_vcs.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:117 +#: 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:65 +#: kallithea/templates/files/files_delete.html:44 +#: kallithea/templates/files/files_edit.html:68 +#: kallithea/templates/pullrequests/pullrequest.html:89 +msgid "Reset" +msgstr "Скід" + +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:9 +msgid "Gist" +msgstr "Gist" + +#: kallithea/templates/admin/gists/show.html:10 +#: kallithea/templates/email_templates/changeset_comment.html:15 +#: kallithea/templates/email_templates/pull_request.html:10 +#: kallithea/templates/email_templates/pull_request_comment.html:15 +msgid "URL" +msgstr "URL" + +#: kallithea/templates/admin/gists/show.html:37 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:39 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:56 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:76 +#: kallithea/templates/changeset/changeset_file_comment.html:50 +#: kallithea/templates/files/files_source.html:39 +#: kallithea/templates/files/files_source.html:42 +#: kallithea/templates/files/files_source.html:45 +msgid "Delete" +msgstr "Выдаліць" + +#: kallithea/templates/admin/gists/show.html:56 +msgid "Confirm to delete this Gist" +msgstr "Пацвердзіце выдаленне гэтай gist-запісы" + +#: kallithea/templates/admin/gists/show.html:63 +#: kallithea/templates/changeset/changeset_file_comment.html:91 +#: kallithea/templates/changeset/changeset_file_comment.html:207 +#: kallithea/templates/data_table/_dt_elements.html:167 +#: kallithea/templates/data_table/_dt_elements.html:183 +#: kallithea/templates/files/diff_2way.html:56 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/files/files_source.html:44 +#: kallithea/templates/pullrequests/pullrequest_show.html:41 +msgid "Edit" +msgstr "Рэдагаваць" + +#: kallithea/templates/admin/gists/show.html:65 +#: kallithea/templates/files/files_edit.html:49 +#: kallithea/templates/files/files_source.html:34 +msgid "Show as Raw" +msgstr "Паказаць толькі тэкст" + +#: kallithea/templates/admin/gists/show.html:73 +msgid "created" +msgstr "створана" + +#: kallithea/templates/admin/gists/show.html:86 +#: kallithea/templates/files/files_source.html:73 +msgid "Show as raw" +msgstr "Паказаць толькі тэкст" + +#: kallithea/templates/admin/my_account/my_account.html:5 +#: kallithea/templates/admin/my_account/my_account.html:9 +#: kallithea/templates/base/base.html:346 +msgid "My Account" +msgstr "Мой Акаўнт" + +#: kallithea/templates/admin/my_account/my_account.html:35 +#: kallithea/templates/admin/users/user_edit.html:29 +msgid "Profile" +msgstr "Профіль" + +#: kallithea/templates/admin/my_account/my_account.html:37 +#: kallithea/templates/admin/users/user_edit.html:30 +msgid "API Keys" +msgstr "API-ключы" + +#: kallithea/templates/admin/my_account/my_account.html:38 +msgid "My Emails" +msgstr "Мае адрасы E-mail" + +#: kallithea/templates/admin/my_account/my_account.html:39 +msgid "My Repositories" +msgstr "Мае рэпазітары" + +#: kallithea/templates/admin/my_account/my_account.html:40 +#: kallithea/templates/journal/journal.html:53 +msgid "Watched" +msgstr "Прагледжана" + +#: kallithea/templates/admin/my_account/my_account.html:41 +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 "" + +#: 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/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 "Дадатковыя адрасы e-mail не пазначаны." + +#: 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:11 +msgid "Change your avatar at" +msgstr "Зменіце аватар праз сайт" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:9 +msgid "Using" +msgstr "Выкарыстоўваецца" + +#: kallithea/templates/admin/my_account/my_account_profile.html:14 +#: kallithea/templates/admin/users/user_edit_profile.html:11 +msgid "Avatars are disabled" +msgstr "Аватары адключаны" + +#: kallithea/templates/admin/my_account/my_account_profile.html:15 +msgid "Missing email, please update your user email address." +msgstr "Не паказаны email. Калі ласка, абновіце ваш email." + +#: kallithea/templates/admin/my_account/my_account_profile.html:16 +#: kallithea/templates/admin/users/user_edit_profile.html:15 +msgid "current IP" +msgstr "бягучы IP-адрас" + +#: kallithea/templates/admin/my_account/my_account_profile.html:28 +msgid "" +"Your user is in an external Source of Record; some details cannot be managed " +"here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:1 +msgid "Repositories You Own" +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:46 +#: kallithea/templates/bookmarks/bookmarks.html:81 +#: kallithea/templates/branches/branches.html:81 +#: kallithea/templates/journal/journal.html:200 +#: kallithea/templates/journal/journal.html:291 +#: kallithea/templates/tags/tags.html:81 +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:9 +msgid "My Notifications" +msgstr "Мае апавяшчэнні" + +#: kallithea/templates/admin/notifications/notifications.html:24 +msgid "All" +msgstr "Усё" + +#: kallithea/templates/admin/notifications/notifications.html:25 +msgid "Comments" +msgstr "Каментары" + +#: kallithea/templates/admin/notifications/notifications.html:26 +#: kallithea/templates/base/base.html:186 +msgid "Pull Requests" +msgstr "Pull-запыты" + +#: kallithea/templates/admin/notifications/notifications.html:30 +msgid "Mark All Read" +msgstr "Адзначыць усё як прачытаныя" + +#: kallithea/templates/admin/notifications/notifications_data.html:40 +msgid "No notifications here yet" +msgstr "Апавяшчэнняў няма" + +#: kallithea/templates/admin/notifications/show_notification.html:5 +#: kallithea/templates/admin/notifications/show_notification.html:11 +msgid "Show Notification" +msgstr "Паказаць апавяшчэнне" + +#: kallithea/templates/admin/notifications/show_notification.html:9 +#: kallithea/templates/base/base.html:345 +msgid "Notifications" +msgstr "Апавяшчэнні" + +#: kallithea/templates/admin/permissions/permissions.html:5 +msgid "Permissions Administration" +msgstr "Кіраванне прывілеямі" + +#: kallithea/templates/admin/permissions/permissions.html:11 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:42 +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/admin/user_groups/user_group_edit.html:32 +#: kallithea/templates/base/base.html:64 +msgid "Permissions" +msgstr "Прывілеі" + +#: kallithea/templates/admin/permissions/permissions.html:28 +#: kallithea/templates/admin/settings/settings.html:29 +msgid "Global" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:29 +#: kallithea/templates/admin/users/user_edit.html:34 +msgid "IP Whitelist" +msgstr "Белы спіс IP" + +#: kallithea/templates/admin/permissions/permissions.html:30 +msgid "Overview" +msgstr "Агляд" + +#: kallithea/templates/admin/permissions/permissions_globals.html:7 +msgid "Anonymous access" +msgstr "Ананімны доступ" + +#: kallithea/templates/admin/permissions/permissions_globals.html:13 +#, python-format +msgid "" +"Allow access to Kallithea without needing 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:48 +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 "" +"Абраныя прывілеі будуць усталяваны па змаўчанні для кожнай групы " +"рэпазітароў. Улічыце, што раней усталяваныя прывілеі па змаўчанні для груп " +"рэпазітароў будуць скінуты" + +#: 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 "Стварэнне рэпазітара" + +#: 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 a repository group 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 "Рэгістрацыя" + +#: 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 "Белы спіс 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" + +#: 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-адрасы." + +#: kallithea/templates/admin/permissions/permissions_ips.html:32 +#: kallithea/templates/admin/users/user_edit_ips.html:42 +msgid "New ip address" +msgstr "Новы IP-адрас" + +#: kallithea/templates/admin/permissions/permissions_perms.html:1 +msgid "Default User Permissions Overview" +msgstr "Агляд мае рацыю карыстачоў па змаўчанні" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:11 +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:11 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:105 +#: kallithea/templates/admin/repo_groups/repo_groups.html:10 +#: kallithea/templates/base/base.html:61 kallithea/templates/base/base.html:80 +msgid "Repository Groups" +msgstr "Групы рэпазітароў" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:33 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:8 +#: kallithea/templates/admin/user_groups/user_group_add.html:32 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:7 +msgid "Group name" +msgstr "Імя групы" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:51 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26 +msgid "Group parent" +msgstr "Бацькоўская група" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:60 +#: kallithea/templates/admin/repos/repo_add_base.html:50 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:64 +#: 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:21 +msgid "Add Child Group" +msgstr "Дадаць падгрупу" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:40 +#: kallithea/templates/admin/repos/repo_edit.html:12 +#: kallithea/templates/admin/repos/repo_edit.html:40 +#: kallithea/templates/admin/settings/settings.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:29 +#: kallithea/templates/base/base.html:67 +#: kallithea/templates/base/base.html:154 +#: kallithea/templates/data_table/_dt_elements.html:43 +#: kallithea/templates/data_table/_dt_elements.html:47 +msgid "Settings" +msgstr "Налады" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:41 +#: kallithea/templates/admin/repos/repo_edit.html:46 +#: kallithea/templates/admin/user_groups/user_group_edit.html:30 +#: kallithea/templates/admin/users/user_edit.html:31 +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:147 +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 рэпазітар" +msgstr[1] "Пацвердзіце выдаленне групы %s, утрымоўвалай %s рэпазітара" +msgstr[2] "Пацвердзіце выдаленне групы %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 "па змаўчанні" + +#: 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_edit_settings.html:53 +msgid "Remove this group" +msgstr "Выдаліць гэту групу" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:53 +msgid "Confirm to delete this group" +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:9 +msgid "Home" +msgstr "Дахаты" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:13 +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:48 +msgid "Number of Top-level Repositories" +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:29 +msgid "Clone from" +msgstr "Кланаваць з" + +#: kallithea/templates/admin/repos/repo_add_base.html:27 +msgid "Optional URL from which repository should be cloned." +msgstr "Апцыянальны URL, з якога патрабуецца скланаваць рэпазітар." + +#: kallithea/templates/admin/repos/repo_add_base.html:36 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +#: kallithea/templates/forks/fork.html:42 +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/admin/repos/repo_edit_settings.html:46 +#: kallithea/templates/forks/fork.html:52 +msgid "Optionally 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:58 +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 "Стварэнне рэпазітара %s" + +#: kallithea/templates/admin/repos/repo_creating.html:13 +msgid "Creating repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:27 +#, python-format +msgid "" +"Repository \"%(repo_name)s\" is being created, you will be redirected when " +"this process is finished.repo_name" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:39 +msgid "" +"We're sorry but error occurred 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 "Налады рэпазітара %s" + +#: kallithea/templates/admin/repos/repo_edit.html:49 +msgid "Extra Fields" +msgstr "Дадатковыя палі" + +#: kallithea/templates/admin/repos/repo_edit.html:52 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:55 +msgid "Remote" +msgstr "Выдалены" + +#: kallithea/templates/admin/repos/repo_edit.html:58 +#: kallithea/templates/summary/statistics.html:8 +#: kallithea/templates/summary/summary.html:174 +#: kallithea/templates/summary/summary.html:175 +msgid "Statistics" +msgstr "Статыстыка" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +msgid "Parent" +msgstr "Бацькоўская група" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:5 +#: kallithea/templates/admin/repos/repo_edit_fork.html:5 +msgid "Set" +msgstr "Набор" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:8 +#: 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:22 +msgid "Public Journal Visibility" +msgstr "Доступ да публічнага часопіса" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:30 +msgid "Remove from public journal" +msgstr "Выдаліць з агульнадаступнага часопіса" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:35 +msgid "Add to Public Journal" +msgstr "Дадаць у публічны часопіс" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:41 +msgid "" +"All actions done in this repository will be visible to everyone in the " +"public journal." +msgstr "" +"Усе выконваемыя з гэтым рэпазітаром дзеянні будуць адлюстроўвацца ў " +"публічным часопісе." + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:47 +msgid "Change Locking" +msgstr "Уключыць блакаванне" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:53 +msgid "Confirm to unlock repository." +msgstr "Пацвердзіце здыманне блакавання з рэпазітара." + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:55 +msgid "Unlock Repository" +msgstr "Разблакаваць рэпазітар" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:61 +msgid "Confirm to lock repository." +msgstr "Пацвердзіце блакаванне рэпазітара." + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:63 +msgid "Lock Repository" +msgstr "Заблакаваць рэпазітар" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:65 +msgid "Repository is not locked" +msgstr "Рэпазітар не заблакаваны" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:69 +msgid "" +"Force locking on the repository. Works only when anonymous access is " +"disabled. Triggering a pull locks the repository. The user who is pulling " +"locks the repository; only the user who pulled and locked it can unlock it " +"by doing a push." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:80 +#: 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:82 +msgid "Delete this Repository" +msgstr "Выдаліць гэты рэпазітар" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:85 +#, 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:86 +msgid "Detach forks" +msgstr "Адлучыць fork'і" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:87 +msgid "Delete forks" +msgstr "Выдаліць fork'і" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:91 +msgid "" +"The deleted repository will be moved away and hidden until the administrator " +"expires it. The administrator can both permanently delete it or restore it." +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, the " +"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:49 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:24 +#: kallithea/templates/admin/user_groups/user_groups.html:49 +#: kallithea/templates/admin/users/user_add.html:88 +#: kallithea/templates/admin/users/user_edit_profile.html:105 +#: kallithea/templates/admin/users/users.html:54 +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 a 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 the above URL guarantees that this " +"repository will always be accessible under such URL.\n" +" Useful 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 +#: kallithea/templates/summary/summary.html:72 +msgid "Clone URL" +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 "URL used for doing remote pulls." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:55 +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:51 +msgid "State" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:5 +msgid "Settings Administration" +msgstr "Адміністраванне налад" + +#: kallithea/templates/admin/settings/settings.html:27 +msgid "VCS" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:28 +msgid "Remap and Rescan" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:30 +msgid "Visual" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:32 +#: kallithea/templates/admin/settings/settings_vcs.html:19 +msgid "Hooks" +msgstr "Хукі" + +#: kallithea/templates/admin/settings/settings.html:33 +msgid "Full Text Search" +msgstr "" + +#: kallithea/templates/admin/settings/settings.html:34 +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 "Прывітанне для HTTP-аўтэнтыфікацыі" + +#: kallithea/templates/admin/settings/settings_global.html:27 +msgid "Analytics HTML block" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:31 +msgid "" +"HTML with JavaScript for web analytics systems like Google Analytics or " +"Piwik. This will be added at the bottom of every page." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:37 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:41 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:47 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:51 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha on " +"registration." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:56 +#: kallithea/templates/admin/settings/settings_vcs.html:80 +#: kallithea/templates/admin/settings/settings_visual.html:116 +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:68 +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 "" +"Check this option to remove references to repositories that no longer exist " +"in on the filesystem." +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 "Check this to reload data and clear cache keys for all repositories." +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 Kallithea's Git hooks are installed for each repository. Current " +"hooks will be updated to the 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 reindexeses all of the repositories 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 "Версія Git" + +#: 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 "Запытваць SSL для аперацый з VCS" + +#: kallithea/templates/admin/settings/settings_vcs.html:13 +msgid "" +"Activate to require SSL both pushing and pulling. If SSL certificate is " +"missing, it will return an 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 "Уключыць падтрымку hgsubversion" + +#: kallithea/templates/admin/settings/settings_vcs.html:53 +msgid "" +"Requires hgsubversion library to be installed. Enables cloning of remote " +"Subversion repositories while converting them to Mercurial." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:64 +msgid "Location of repositories" +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 are stored. After changing this " +"value, a restart and rescan of the repository folder are both 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 another avatar server application.\n" +" The 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}'.\n" +" The following " +"variables are available:\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:55 +msgid "Dashboard items" +msgstr "Элементы панэлі" + +#: kallithea/templates/admin/settings/settings_visual.html:59 +msgid "" +"Number of items displayed in the main page dashboard before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:65 +msgid "Admin pages items" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:69 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:75 +msgid "Icons" +msgstr "Абразкі" + +#: kallithea/templates/admin/settings/settings_visual.html:80 +msgid "Show public repo icon on repositories" +msgstr "Паказваць абразкі публічных рэпазітароў" + +#: kallithea/templates/admin/settings/settings_visual.html:84 +msgid "Show private repo icon on repositories" +msgstr "Паказваць абразкі прыватных рэпазітароў" + +#: kallithea/templates/admin/settings/settings_visual.html:86 +msgid "Show public/private icons next to repository names." +msgstr "Паказваць абразкі публічных рэпазітароў." + +#: kallithea/templates/admin/settings/settings_visual.html:92 +msgid "Meta-Tagging" +msgstr "Метатэгіраванне" + +#: kallithea/templates/admin/settings/settings_visual.html:97 +msgid "Stylify recognised meta tags:" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:111 +msgid "" +"Parses meta tags from the 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:10 +#: kallithea/templates/admin/user_groups/user_group_edit.html:11 +#: kallithea/templates/base/base.html:63 kallithea/templates/base/base.html:83 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:25 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:44 +#: 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:31 +msgid "Default permissions" +msgstr "Стандартныя прывілеі" + +#: kallithea/templates/admin/user_groups/user_group_edit.html:33 +#: 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:48 +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 "Пацвердзіце выдаленне наступнай групы карыстачоў: %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:17 +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:49 +msgid "Available members" +msgstr "Даступныя ўдзельнікі" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User Groups Administration" +msgstr "Адміністраванне груп карыстачоў" + +#: kallithea/templates/admin/user_groups/user_groups.html:10 +msgid "user groups" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:5 +msgid "Add user" +msgstr "Дадаць карыстача" + +#: kallithea/templates/admin/users/user_add.html:10 +#: kallithea/templates/admin/users/user_edit.html:11 +#: kallithea/templates/admin/users/users.html:10 +#: kallithea/templates/base/base.html:62 +msgid "Users" +msgstr "Карыстачы" + +#: kallithea/templates/admin/users/user_add.html:12 +#: kallithea/templates/admin/users/users.html:24 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:50 +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:32 +msgid "Default Permissions" +msgstr "Стандартныя прывілеі" + +#: kallithea/templates/admin/users/user_edit.html:33 +msgid "Emails" +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 +#: kallithea/templates/admin/users/users.html:53 +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:56 +msgid "Auth Type" +msgstr "" + +#: kallithea/templates/base/base.html:18 +#, python-format +msgid "Server instance: %s" +msgstr "Асобнік сервера: %s" + +#: kallithea/templates/base/base.html:30 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:122 +msgid "Create Fork" +msgstr "Стварыць форк" + +#: kallithea/templates/base/base.html:133 +#: kallithea/templates/data_table/_dt_elements.html:11 +#: kallithea/templates/data_table/_dt_elements.html:15 +#: kallithea/templates/summary/summary.html:8 +msgid "Summary" +msgstr "Агульныя звесткі" + +#: kallithea/templates/base/base.html:135 +#: kallithea/templates/base/base.html:137 +#: kallithea/templates/changelog/changelog.html:14 +#: kallithea/templates/data_table/_dt_elements.html:19 +#: kallithea/templates/data_table/_dt_elements.html:23 +msgid "Changelog" +msgstr "Гісторыя змен" + +#: kallithea/templates/base/base.html:139 +#: kallithea/templates/data_table/_dt_elements.html:27 +#: kallithea/templates/data_table/_dt_elements.html:31 +#: kallithea/templates/files/files.html:11 +msgid "Files" +msgstr "Файлы" + +#: kallithea/templates/base/base.html:141 +msgid "Switch To" +msgstr "Пераключыцца на" + +#: kallithea/templates/base/base.html:148 +#: kallithea/templates/base/base.html:150 +msgid "Options" +msgstr "Опцыі" + +#: kallithea/templates/base/base.html:158 +#: kallithea/templates/forks/forks_data.html:21 +msgid "Compare Fork" +msgstr "Параўнаць форк" + +#: kallithea/templates/base/base.html:160 +#: kallithea/templates/bookmarks/bookmarks.html:56 +#: kallithea/templates/bookmarks/bookmarks_data.html:13 +#: kallithea/templates/branches/branches.html:56 +#: kallithea/templates/branches/branches_data.html:13 +#: kallithea/templates/tags/tags.html:56 +#: kallithea/templates/tags/tags_data.html:13 +msgid "Compare" +msgstr "Параўнаць" + +#: kallithea/templates/base/base.html:162 +#: kallithea/templates/base/base.html:250 +#: kallithea/templates/search/search.html:14 +#: kallithea/templates/search/search.html:54 +msgid "Search" +msgstr "Пошук" + +#: kallithea/templates/base/base.html:166 +msgid "Unlock" +msgstr "Разблакаваць" + +#: kallithea/templates/base/base.html:168 +msgid "Lock" +msgstr "Заблакаваць" + +#: kallithea/templates/base/base.html:176 +msgid "Follow" +msgstr "Назіраць" + +#: kallithea/templates/base/base.html:177 +msgid "Unfollow" +msgstr "Не назіраць" + +#: kallithea/templates/base/base.html:180 +#: kallithea/templates/data_table/_dt_elements.html:35 +#: kallithea/templates/data_table/_dt_elements.html:39 +#: kallithea/templates/forks/fork.html:9 +msgid "Fork" +msgstr "Форк" + +#: kallithea/templates/base/base.html:181 +#: kallithea/templates/pullrequests/pullrequest.html:88 +msgid "Create Pull Request" +msgstr "Стварыць Pull запыт" + +#: kallithea/templates/base/base.html:186 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "Паказаць pull-запыты для %s" + +#: kallithea/templates/base/base.html:224 +msgid "Show recent activity" +msgstr "Паказаць апошнюю актыўнасць" + +#: kallithea/templates/base/base.html:225 +#: kallithea/templates/journal/journal.html:4 +#: kallithea/templates/journal/journal.html:12 +msgid "Journal" +msgstr "Часопіс" + +#: kallithea/templates/base/base.html:230 +#: kallithea/templates/base/base.html:231 +msgid "Public journal" +msgstr "Агульнадаступны часопіс" + +#: kallithea/templates/base/base.html:236 +msgid "Show public gists" +msgstr "Паказаць публічныя запісы" + +#: kallithea/templates/base/base.html:237 +msgid "Gists" +msgstr "Gist" + +#: kallithea/templates/base/base.html:241 +msgid "All Public Gists" +msgstr "Усе публічныя Gist-запісы" + +#: kallithea/templates/base/base.html:243 +msgid "My Public Gists" +msgstr "Мае публічныя Gist-запісы" + +#: kallithea/templates/base/base.html:244 +msgid "My Private Gists" +msgstr "Мае прыватныя Gist-запісы" + +#: kallithea/templates/base/base.html:249 +msgid "Search in repositories" +msgstr "Пошук па рэпазітарах" + +#: kallithea/templates/base/base.html:272 +#: kallithea/templates/base/base.html:273 +#: kallithea/templates/pullrequests/pullrequest_show_my.html:4 +#: kallithea/templates/pullrequests/pullrequest_show_my.html:8 +msgid "My Pull Requests" +msgstr "Мае Pull-запыты" + +#: kallithea/templates/base/base.html:292 +msgid "Not Logged In" +msgstr "Не аўтарызаваны" + +#: kallithea/templates/base/base.html:299 +msgid "Login to Your Account" +msgstr "Аўтарызавацца" + +#: kallithea/templates/base/base.html:322 +msgid "Forgot password ?" +msgstr "Забыліся пароль?" + +#: kallithea/templates/base/base.html:347 +msgid "Log Out" +msgstr "Выйсце" + +#: kallithea/templates/base/base.html:395 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:524 +msgid "Keyboard shortcuts" +msgstr "" + +#: kallithea/templates/base/base.html:533 +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 "Ствараць fork ад рэпазітароў" + +#: kallithea/templates/base/default_perms_box.html:57 +msgid "Select this option to allow repository forking for this user" +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 "Прывілеі яшчэ не прызначаны" + +#: kallithea/templates/base/perms_summary.html:30 +#: kallithea/templates/base/perms_summary.html:54 +msgid "Permission" +msgstr "Прывілей" + +#: 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:22 +msgid "Add Another Comment" +msgstr "Дадаць яшчэ адзін каментар" + +#: kallithea/templates/base/root.html:23 +#: kallithea/templates/data_table/_dt_elements.html:216 +msgid "Stop following this repository" +msgstr "Адмяніць назіранне за рэпазітаром" + +#: kallithea/templates/base/root.html:24 +msgid "Start following this repository" +msgstr "Назіраць за рэпазітаром" + +#: kallithea/templates/base/root.html:25 +msgid "Group" +msgstr "Група" + +#: kallithea/templates/base/root.html:26 +msgid "members" +msgstr "удзельнікі" + +#: kallithea/templates/base/root.html:27 +msgid "Loading ..." +msgstr "Загрузка..." + +#: kallithea/templates/base/root.html:28 +msgid "loading ..." +msgstr "загрузка..." + +#: kallithea/templates/base/root.html:29 +msgid "Search truncated" +msgstr "Пошук усечаны" + +#: kallithea/templates/base/root.html:30 +msgid "No matching files" +msgstr "Няма супадзенняў" + +#: kallithea/templates/base/root.html:31 +#: kallithea/templates/pullrequests/pullrequest_show_all.html:30 +msgid "Open New Pull Request" +msgstr "Стварыць новы pull-запыт" + +#: kallithea/templates/base/root.html:32 +msgid "Open New Pull Request for Selected Changesets" +msgstr "Адкрыць новы pull-request для абраных набораў змен" + +#: kallithea/templates/base/root.html:33 +msgid "Show Selected Changesets __S → __E" +msgstr "Паказаць абраныя наборы змен: __S → __E" + +#: kallithea/templates/base/root.html:34 +msgid "Show Selected Changeset __S" +msgstr "Паказаць абраны набор змен: __S" + +#: kallithea/templates/base/root.html:35 +msgid "Selection Link" +msgstr "Спасылка выбару" + +#: kallithea/templates/base/root.html:36 +#: kallithea/templates/changeset/diff_block.html:8 +msgid "Collapse Diff" +msgstr "Згарнуць параўнанне" + +#: kallithea/templates/base/root.html:37 +msgid "Expand Diff" +msgstr "Расчыніць параўнанне" + +#: kallithea/templates/base/root.html:38 +msgid "Failed to revoke permission" +msgstr "Не атрымалася адклікаць прывілеі" + +#: kallithea/templates/base/root.html:39 +msgid "Confirm to revoke permission for {0}: {1} ?" +msgstr "Пацвердзіце выдаленне прывілею для {0}: {1} ?" + +#: kallithea/templates/base/root.html:43 +msgid "Specify changeset" +msgstr "Абраць набор змен" + +#: kallithea/templates/bookmarks/bookmarks.html:5 +#, python-format +msgid "%s Bookmarks" +msgstr "Закладкі %s" + +#: kallithea/templates/bookmarks/bookmarks.html:26 +msgid "Compare Bookmarks" +msgstr "" + +#: kallithea/templates/bookmarks/bookmarks.html:53 +#: kallithea/templates/bookmarks/bookmarks_data.html:10 +#: kallithea/templates/branches/branches.html:53 +#: kallithea/templates/branches/branches_data.html:10 +#: kallithea/templates/changelog/changelog_summary_data.html:10 +#: kallithea/templates/pullrequests/pullrequest_data.html:16 +#: kallithea/templates/tags/tags.html:53 +#: kallithea/templates/tags/tags_data.html:10 +msgid "Author" +msgstr "Аўтар" + +#: kallithea/templates/bookmarks/bookmarks.html:54 +#: kallithea/templates/bookmarks/bookmarks_data.html:12 +#: kallithea/templates/branches/branches.html:54 +#: kallithea/templates/branches/branches_data.html:12 +#: kallithea/templates/changelog/changelog_summary_data.html:7 +#: kallithea/templates/pullrequests/pullrequest.html:62 +#: kallithea/templates/pullrequests/pullrequest.html:78 +#: kallithea/templates/tags/tags.html:54 +#: kallithea/templates/tags/tags_data.html:12 +msgid "Revision" +msgstr "Рэвізія" + +#: kallithea/templates/branches/branches.html:5 +#, python-format +msgid "%s Branches" +msgstr "Галінкі %s" + +#: kallithea/templates/branches/branches.html:26 +msgid "Compare Branches" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:6 +#, python-format +msgid "%s Changelog" +msgstr "Логі змен %s" + +#: 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[2] "Паказаны %d з %d рэвізій" + +#: kallithea/templates/changelog/changelog.html:42 +msgid "Show" +msgstr "Паказаць" + +#: kallithea/templates/changelog/changelog.html:52 +msgid "Clear selection" +msgstr "Ачысціць выбар" + +#: kallithea/templates/changelog/changelog.html:55 +msgid "Go to tip of repository" +msgstr "Перайсці на верхавіну рэпазітара" + +#: kallithea/templates/changelog/changelog.html:60 +#: kallithea/templates/forks/forks_data.html:19 +#, python-format +msgid "Compare fork with %s" +msgstr "Параўнаць fork з %s" + +#: kallithea/templates/changelog/changelog.html:62 +#, python-format +msgid "Compare fork with parent repo (%s)" +msgstr "Параўнаць форк з бацькоўскім рэпазітаром (%s)" + +#: kallithea/templates/changelog/changelog.html:66 +#: kallithea/templates/files/files.html:29 +msgid "Branch filter:" +msgstr "Адфільтраваць галінку:" + +#: kallithea/templates/changelog/changelog.html:92 +#: kallithea/templates/changelog/changelog_summary_data.html:20 +#, 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:96 +#: kallithea/templates/compare/compare_cs.html:24 +#, python-format +msgid "Changeset status: %s" +msgstr "Статут набору змен: %s" + +#: kallithea/templates/changelog/changelog.html:115 +#: kallithea/templates/compare/compare_cs.html:48 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:124 +#: kallithea/templates/compare/compare_cs.html:30 +msgid "Changeset has comments" +msgstr "Каментары адсутнічаюць" + +#: kallithea/templates/changelog/changelog.html:134 +#: kallithea/templates/changelog/changelog_summary_data.html:54 +#: kallithea/templates/changeset/changeset.html:94 +#: kallithea/templates/changeset/changeset_range.html:92 +#, python-format +msgid "Bookmark %s" +msgstr "Закладка %s" + +#: kallithea/templates/changelog/changelog.html:140 +#: kallithea/templates/changelog/changelog_summary_data.html:60 +#: kallithea/templates/changeset/changeset.html:101 +#: kallithea/templates/changeset/changeset_range.html:98 +#, python-format +msgid "Tag %s" +msgstr "Пазнака %s" + +#: kallithea/templates/changelog/changelog.html:145 +#: kallithea/templates/changelog/changelog_summary_data.html:65 +#: kallithea/templates/changeset/changeset.html:106 +#: kallithea/templates/changeset/changeset_range.html:102 +#, python-format +msgid "Branch %s" +msgstr "Галінка %s" + +#: kallithea/templates/changelog/changelog.html:290 +msgid "There are no changes yet" +msgstr "Змен яшчэ няма" + +#: kallithea/templates/changelog/changelog_details.html:4 +#: kallithea/templates/changeset/changeset.html:77 +msgid "Removed" +msgstr "Выдалена" + +#: kallithea/templates/changelog/changelog_details.html:5 +#: kallithea/templates/changeset/changeset.html:78 +msgid "Changed" +msgstr "Зменена" + +#: kallithea/templates/changelog/changelog_details.html:6 +#: kallithea/templates/changeset/changeset.html:79 +#: kallithea/templates/changeset/diff_block.html:80 +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:81 +#: kallithea/templates/changeset/changeset.html:82 +#: kallithea/templates/changeset/changeset.html:83 +#, python-format +msgid "Affected %s files" +msgstr "Закранае %s файлаў" + +#: kallithea/templates/changelog/changelog_summary_data.html:8 +#: kallithea/templates/files/files_add.html:60 +#: kallithea/templates/files/files_delete.html:39 +#: kallithea/templates/files/files_edit.html:63 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:9 +#: kallithea/templates/pullrequests/pullrequest_data.html:17 +msgid "Age" +msgstr "Узрост" + +#: kallithea/templates/changelog/changelog_summary_data.html:11 +msgid "Refs" +msgstr "Спасылкі" + +#: kallithea/templates/changelog/changelog_summary_data.html:91 +msgid "Add or upload files directly via Kallithea" +msgstr "Дадаць ці загрузіць файлы праз Kallithea" + +#: kallithea/templates/changelog/changelog_summary_data.html:94 +#: kallithea/templates/files/files_add.html:21 +#: kallithea/templates/files/files_ypjax.html:9 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/changelog/changelog_summary_data.html:100 +msgid "Push new repo" +msgstr "Адправіць новы рэпазітар" + +#: kallithea/templates/changelog/changelog_summary_data.html:108 +msgid "Existing repository?" +msgstr "Існы рэпазітар?" + +#: kallithea/templates/changeset/changeset.html:8 +#, python-format +msgid "%s Changeset" +msgstr "%s Змены" + +#: kallithea/templates/changeset/changeset.html:36 +msgid "parent rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:42 +msgid "child rev." +msgstr "" + +#: kallithea/templates/changeset/changeset.html:50 +#: kallithea/templates/changeset/changeset_file_comment.html:43 +#: kallithea/templates/changeset/changeset_range.html:48 +msgid "Changeset status" +msgstr "Статут змен" + +#: kallithea/templates/changeset/changeset.html:54 +#: kallithea/templates/changeset/diff_block.html:27 +#: kallithea/templates/files/diff_2way.html:49 +msgid "Raw diff" +msgstr "Адлюстраваць у фармаце diff" + +#: kallithea/templates/changeset/changeset.html:57 +msgid "Patch diff" +msgstr "Ужыць рознаснае выпраўленне (Patch diff)" + +#: kallithea/templates/changeset/changeset.html:60 +#: kallithea/templates/changeset/diff_block.html:30 +#: kallithea/templates/files/diff_2way.html:52 +msgid "Download diff" +msgstr "Запампаваць diff" + +#: kallithea/templates/changeset/changeset.html:89 +#: kallithea/templates/changeset/changeset_range.html:88 +msgid "merge" +msgstr "звесці" + +#: kallithea/templates/changeset/changeset.html:123 +msgid "Grafted from:" +msgstr "Перанесена з:" + +#: kallithea/templates/changeset/changeset.html:129 +msgid "Transplanted from:" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:137 +#: kallithea/templates/compare/compare_diff.html:54 +#: kallithea/templates/pullrequests/pullrequest_show.html:307 +#, python-format +msgid "%s file changed" +msgid_plural "%s files changed" +msgstr[0] "%s файл зменены" +msgstr[1] "%s файлаў зменена" +msgstr[2] "%s файла зменена" + +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/compare/compare_diff.html:56 +#: kallithea/templates/pullrequests/pullrequest_show.html:309 +#, 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 выдаленне" +msgstr[1] "%s файла зменена: %s даданні, %s выдаленні" +msgstr[2] "%s файлаў зменена: %s даданняў, %s выдаленняў" + +#: kallithea/templates/changeset/changeset.html:153 +#: kallithea/templates/changeset/changeset.html:166 +#: kallithea/templates/pullrequests/pullrequest_show.html:328 +#: kallithea/templates/pullrequests/pullrequest_show.html:351 +msgid "Show full diff anyway" +msgstr "Паказаць поўны diff" + +#: kallithea/templates/changeset/changeset.html:224 +#: kallithea/templates/changeset/changeset.html:261 +msgid "no revisions" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:24 +msgid "Status change from pull request" +msgstr "Змена статуту" + +#: kallithea/templates/changeset/changeset_file_comment.html:25 +#: kallithea/templates/changeset/changeset_file_comment.html:28 +msgid "No title" +msgstr "Няма загалоўка" + +#: kallithea/templates/changeset/changeset_file_comment.html:27 +msgid "Comment from pull request" +msgstr "Каментар у pull-запыце" + +#: kallithea/templates/changeset/changeset_file_comment.html:32 +msgid "Status change on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:34 +msgid "Comment on changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:50 +msgid "Delete comment?" +msgstr "Выдаліць каментар?" + +#: kallithea/templates/changeset/changeset_file_comment.html:67 +msgid "Commenting on line {1}." +msgstr "Каментар да радка {1}." + +#: kallithea/templates/changeset/changeset_file_comment.html:68 +#: kallithea/templates/changeset/changeset_file_comment.html:163 +#, python-format +msgid "Comments parsed using %s syntax with %s support." +msgstr "" +"Парсінг каментароў выкананы з выкарыстаннем сінтаксісу %s з падтрымкай %s." + +#: kallithea/templates/changeset/changeset_file_comment.html:70 +#: kallithea/templates/changeset/changeset_file_comment.html:165 +msgid "Use @username inside this text to notify another user" +msgstr "" +"Выкарыстоўвайце @імя_карыстача ў тэксце, каб адправіць абвестку пэўнаму " +"карыстачу" + +#: kallithea/templates/changeset/changeset_file_comment.html:80 +#: kallithea/templates/changeset/changeset_file_comment.html:199 +msgid "Comment preview" +msgstr "Папярэдні прагляд каментара" + +#: kallithea/templates/changeset/changeset_file_comment.html:85 +msgid "Submitting ..." +msgstr "Ужыванне..." + +#: kallithea/templates/changeset/changeset_file_comment.html:88 +#: kallithea/templates/changeset/changeset_file_comment.html:205 +msgid "Comment" +msgstr "Каментаваць" + +#: kallithea/templates/changeset/changeset_file_comment.html:90 +#: kallithea/templates/changeset/changeset_file_comment.html:206 +msgid "Preview" +msgstr "Прадпрагляд" + +#: kallithea/templates/changeset/changeset_file_comment.html:98 +msgid "You need to be logged in to comment." +msgstr "Вам неабходна аўтарызавацца, каб пакідаць каментары." + +#: kallithea/templates/changeset/changeset_file_comment.html:98 +msgid "Login now" +msgstr "Аўтарызавацца цяпер" + +#: kallithea/templates/changeset/changeset_file_comment.html:102 +msgid "Hide" +msgstr "Схаваць" + +#: kallithea/templates/changeset/changeset_file_comment.html:114 +#, python-format +msgid "%d comment" +msgid_plural "%d comments" +msgstr[0] "%d каментар" +msgstr[1] "%d каментара" +msgstr[2] "%d каментароў" + +#: kallithea/templates/changeset/changeset_file_comment.html:115 +#, python-format +msgid "%d inline" +msgid_plural "%d inline" +msgstr[0] "%d да радка" +msgstr[1] "%d да радкоў" +msgstr[2] "%d да радкоў" + +#: kallithea/templates/changeset/changeset_file_comment.html:116 +#, python-format +msgid "%d general" +msgid_plural "%d general" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: kallithea/templates/changeset/changeset_file_comment.html:172 +msgid "Vote for pull request status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:174 +msgid "Set changeset status" +msgstr "Змяніць статут рэвізіі" + +#: kallithea/templates/changeset/changeset_file_comment.html:178 +msgid "No change" +msgstr "Без змен" + +#: kallithea/templates/changeset/changeset_file_comment.html:191 +msgid "Close" +msgstr "Зачыніць" + +#: kallithea/templates/changeset/changeset_range.html:5 +#, python-format +msgid "%s Changesets" +msgstr "%s Змены" + +#: kallithea/templates/changeset/changeset_range.html:56 +msgid "Files affected" +msgstr "Закранутыя файлы" + +#: kallithea/templates/changeset/diff_block.html:21 +#: kallithea/templates/files/diff_2way.html:43 +msgid "Show full diff for this file" +msgstr "Паказаць поўны diff для гэтага файла" + +#: kallithea/templates/changeset/diff_block.html:24 +#: kallithea/templates/changeset/diff_block.html:99 +#: kallithea/templates/files/diff_2way.html:46 +msgid "Show full side-by-side diff for this file" +msgstr "Паказаць поўны diff для гэтага файла" + +#: kallithea/templates/changeset/diff_block.html:38 +msgid "Show inline comments" +msgstr "Паказаць каментары ў радках" + +#: kallithea/templates/changeset/diff_block.html:87 +msgid "Deleted" +msgstr "Выдалены" + +#: kallithea/templates/changeset/diff_block.html:90 +msgid "Renamed" +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_cs.html:61 +msgid "Show merge diff" +msgstr "Паказаць merge diff" + +#: kallithea/templates/compare/compare_cs.html:71 +#: kallithea/templates/pullrequests/pullrequest_show.html:299 +msgid "Common ancestor" +msgstr "Агульны продак" + +#: kallithea/templates/compare/compare_cs.html:75 +msgid "No common ancestor found - repositories are unrelated" +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:83 +msgid "is" +msgstr "адстае на" + +#: kallithea/templates/compare/compare_cs.html:84 +#, python-format +msgid "%s changesets" +msgstr "%s змен" + +#: kallithea/templates/compare/compare_cs.html:85 +msgid "behind" +msgstr "ад" + +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 +#, python-format +msgid "%s Compare" +msgstr "%s Параўнаць" + +#: kallithea/templates/compare/compare_diff.html:13 +#: kallithea/templates/compare/compare_diff.html:35 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:33 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:42 +msgid "Compare revisions, branches, bookmarks, or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:47 +#: kallithea/templates/pullrequests/pullrequest_show.html:294 +#, python-format +msgid "Showing %s commit" +msgid_plural "Showing %s commits" +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:315 +msgid "No files" +msgstr "Няма файлаў" + +#: kallithea/templates/compare/compare_diff.html:78 +#: kallithea/templates/compare/compare_diff.html:89 +msgid "Show full diff" +msgstr "Паказаць поўны diff" + +#: kallithea/templates/data_table/_dt_elements.html:67 +msgid "Mercurial repository" +msgstr "Рэпазітар Mercurial" + +#: kallithea/templates/data_table/_dt_elements.html:69 +msgid "Git repository" +msgstr "Git рэпазітар" + +#: kallithea/templates/data_table/_dt_elements.html:76 +msgid "Public repository" +msgstr "Публічны рэпазітар" + +#: kallithea/templates/data_table/_dt_elements.html:86 +msgid "Repository creation in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:100 +msgid "No changesets yet" +msgstr "Змен яшчэ не было" + +#: kallithea/templates/data_table/_dt_elements.html:107 +#: kallithea/templates/data_table/_dt_elements.html:109 +#, python-format +msgid "Subscribe to %s rss feed" +msgstr "Падпісацца на стужку RSS %s" + +#: kallithea/templates/data_table/_dt_elements.html:115 +#: kallithea/templates/data_table/_dt_elements.html:117 +#, python-format +msgid "Subscribe to %s atom feed" +msgstr "Падпісацца на стужку Atom %s" + +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:5 +#, python-format +msgid "Comment from %s on %s changeset %s mentioned you" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:7 +#, python-format +msgid "Comment from %s on %s changeset %s" +msgstr "Каментар ад %s да набору змен %s %s" + +#: kallithea/templates/email_templates/changeset_comment.html:12 +msgid "The changeset status was changed to" +msgstr "Стан набору змен зменена на" + +#: kallithea/templates/email_templates/main.html:6 +msgid "This is an automatic notification. Don't reply to this mail." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:4 +#, python-format +msgid "Hello %s" +msgstr "Дабрыдзень, %s" + +#: kallithea/templates/email_templates/password_reset.html:6 +msgid "We received a request to create a new password for your account." +msgstr "Мы адправілі запыт на стварэнне новага пароля для вашага акаўнта." + +#: kallithea/templates/email_templates/password_reset.html:7 +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:5 +#, python-format +msgid "%s mentioned you on %s pull request \"%s\"" +msgstr "%s згадаў Вас у каментары да pull-запыту %s \"%s\"" + +#: kallithea/templates/email_templates/pull_request.html:7 +#, python-format +msgid "%s requested your review of %s pull request \"%s\"" +msgstr "%s запытаў рэцэнзаванне pull-запыту %s \"%s\"" + +#: kallithea/templates/email_templates/pull_request_comment.html:4 +#, python-format +msgid "Comment from %s on %s pull request \"%s\"" +msgstr "" + +#: kallithea/templates/email_templates/pull_request_comment.html:9 +msgid "The comment closed the pull request with status" +msgstr "Каментар зачыніў pull-запыт са статутам" + +#: kallithea/templates/email_templates/pull_request_comment.html:11 +msgid "The comment was made with status" +msgstr "Каментар пакінуты са статутам" + +#: kallithea/templates/email_templates/registration.html:6 +msgid "View this user here" +msgstr "Падрабязней пра карыстача" + +#: kallithea/templates/files/diff_2way.html:15 +#, python-format +msgid "%s File side-by-side diff" +msgstr "" + +#: kallithea/templates/files/diff_2way.html:19 +#: kallithea/templates/files/file_diff.html:8 +msgid "File diff" +msgstr "Параўнанне файлаў" + +#: kallithea/templates/files/file_diff.html:4 +#, python-format +msgid "%s File Diff" +msgstr "Параўнанне файла %s" + +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:80 +#, python-format +msgid "%s Files" +msgstr "%s Файлы" + +#: kallithea/templates/files/files_add.html:4 +#, python-format +msgid "%s Files Add" +msgstr "%s Файлаў дададзена" + +#: kallithea/templates/files/files_add.html:40 +#: kallithea/templates/files/files_edit.html:38 +#: kallithea/templates/files/files_ypjax.html:3 +msgid "Location" +msgstr "Размяшчэнне" + +#: kallithea/templates/files/files_add.html:42 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:44 +#: kallithea/templates/files/files_add.html:48 +msgid "or" +msgstr "ці" + +#: kallithea/templates/files/files_add.html:44 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:48 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "New file mode" +msgstr "Рэжым новага файла" + +#: kallithea/templates/files/files_add.html:64 +#: kallithea/templates/files/files_delete.html:43 +#: kallithea/templates/files/files_edit.html:67 +msgid "Commit Changes" +msgstr "Ужыць змены" + +#: kallithea/templates/files/files_browser.html:32 +msgid "revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:33 +msgid "Previous revision" +msgstr "Папярэдняя рэвізія" + +#: kallithea/templates/files/files_browser.html:35 +msgid "Next revision" +msgstr "Наступная рэвізія" + +#: kallithea/templates/files/files_browser.html:41 +msgid "Follow current branch" +msgstr "Адсочваць дадзеную галінку" + +#: kallithea/templates/files/files_browser.html:44 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:48 +msgid "Loading file list..." +msgstr "Загружаецца спіс файлаў..." + +#: kallithea/templates/files/files_browser.html:61 +msgid "Size" +msgstr "Памер" + +#: kallithea/templates/files/files_browser.html:62 +msgid "Mimetype" +msgstr "Тып файла" + +#: kallithea/templates/files/files_browser.html:63 +msgid "Last Revision" +msgstr "Апошняя версія" + +#: kallithea/templates/files/files_browser.html:64 +msgid "Last Modified" +msgstr "Апошняя змена" + +#: kallithea/templates/files/files_browser.html:65 +msgid "Last Committer" +msgstr "Аўтар апошняй рэвізіі" + +#: kallithea/templates/files/files_delete.html:4 +#, python-format +msgid "%s Files Delete" +msgstr "" + +#: kallithea/templates/files/files_delete.html:12 +#: kallithea/templates/files/files_delete.html:31 +msgid "Delete file" +msgstr "" + +#: kallithea/templates/files/files_edit.html:4 +#, python-format +msgid "%s File Edit" +msgstr "" + +#: kallithea/templates/files/files_edit.html:21 +msgid "Edit file" +msgstr "Рэдагаваць файл" + +#: kallithea/templates/files/files_edit.html:48 +#: kallithea/templates/files/files_source.html:32 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:50 +#: kallithea/templates/files/files_source.html:35 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:53 +msgid "Source" +msgstr "Зыходны код" + +#: kallithea/templates/files/files_edit.html:58 +msgid "Editing file" +msgstr "Рэдагаванне файла" + +#: kallithea/templates/files/files_history_box.html:2 +#, python-format +msgid "%s author" +msgid_plural "%s authors" +msgstr[0] "%s аўтар" +msgstr[1] "%s аўтараў" +msgstr[2] "%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 "" + +#: 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 "Рэдагаванне файлаў дазволена толькі ў 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:63 +#, python-format +msgid "Binary file (%s)" +msgstr "Бінарны файл (%s)" + +#: kallithea/templates/files/files_source.html:73 +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 "%s Назіральнікі" + +#: kallithea/templates/followers/followers.html:9 +#: kallithea/templates/summary/summary.html:145 +#: kallithea/templates/summary/summary.html:146 +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:27 +msgid "Fork name" +msgstr "Імя форка" + +#: kallithea/templates/forks/fork.html:62 +msgid "Default revision for files page, downloads, whoosh, and readme." +msgstr "" +"Рэвізія па змаўчанні, з якой будзе вырабляцца выгрузка файлаў пры спампоўцы." + +#: kallithea/templates/forks/fork.html:68 +msgid "Private" +msgstr "Прыватны" + +#: kallithea/templates/forks/fork.html:77 +msgid "Copy permissions" +msgstr "Скапіяваць прывілеі" + +#: kallithea/templates/forks/fork.html:81 +msgid "Copy permissions from forked repository" +msgstr "Скапіяваць прывілеі з форкнутага рэпазітара" + +#: kallithea/templates/forks/fork.html:87 +msgid "Update after clone" +msgstr "Абнаўляць пасля кланавання" + +#: kallithea/templates/forks/fork.html:91 +msgid "Checkout source after making a clone" +msgstr "Спампоўваць зыходнікі пасля стварэння клона" + +#: kallithea/templates/forks/fork.html:96 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 +#, python-format +msgid "%s Forks" +msgstr "Форкі %s" + +#: kallithea/templates/forks/forks.html:9 +#: kallithea/templates/summary/summary.html:151 +#: kallithea/templates/summary/summary.html:152 +msgid "Forks" +msgstr "Адгалінаванні" + +#: kallithea/templates/forks/forks_data.html:17 +msgid "Forked" +msgstr "Форкнута" + +#: kallithea/templates/forks/forks_data.html:43 +msgid "There are no forks yet" +msgstr "Форкі яшчэ не створаны" + +#: kallithea/templates/journal/journal.html:21 +msgid "ATOM journal feed" +msgstr "Стужка часопіса ATOM" + +#: kallithea/templates/journal/journal.html:22 +msgid "RSS journal feed" +msgstr "Стужка часопіса RSS" + +#: kallithea/templates/journal/journal.html:56 +msgid "My Repos" +msgstr "Мае рэпазітары" + +#: kallithea/templates/journal/journal_data.html:61 +msgid "No entries yet" +msgstr "Запісы адсутнічаюць" + +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:21 +msgid "Public Journal" +msgstr "Публічны часопіс" + +#: kallithea/templates/journal/public_journal.html:13 +msgid "ATOM public journal feed" +msgstr "Агульная стужка часопіса ATOM" + +#: kallithea/templates/journal/public_journal.html:14 +msgid "RSS public journal feed" +msgstr "Агульная стужка часопіса RSS" + +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 +msgid "New Pull Request" +msgstr "Новы pull-запыт" + +#: kallithea/templates/pullrequests/pullrequest.html:31 +#: kallithea/templates/pullrequests/pullrequest_data.html:15 +#: kallithea/templates/pullrequests/pullrequest_show.html:29 +#: kallithea/templates/pullrequests/pullrequest_show.html:54 +msgid "Title" +msgstr "Загаловак" + +#: kallithea/templates/pullrequests/pullrequest.html:34 +msgid "Summarize the changes - or leave empty" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:43 +#: kallithea/templates/pullrequests/pullrequest_show.html:66 +msgid "Write a short description on this pull request" +msgstr "Напісаць кароткае пісанне па гэтым запыце" + +#: kallithea/templates/pullrequests/pullrequest.html:49 +msgid "Changeset flow" +msgstr "Струмень змен" + +#: kallithea/templates/pullrequests/pullrequest.html:56 +msgid "Origin repository" +msgstr "Першапачатковы рэпазітар" + +#: kallithea/templates/pullrequests/pullrequest.html:72 +msgid "Destination repository" +msgstr "Рэпазітар прызначэння" + +#: kallithea/templates/pullrequests/pullrequest.html:97 +#: kallithea/templates/pullrequests/pullrequest_show.html:210 +msgid "Pull Request Reviewers" +msgstr "Рэцэнзенты pull-запытаў" + +#: kallithea/templates/pullrequests/pullrequest.html:107 +#: kallithea/templates/pullrequests/pullrequest_show.html:239 +msgid "Type name of reviewer to add" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:6 +msgid "No entries" +msgstr "Запісы отсуствуют" + +#: kallithea/templates/pullrequests/pullrequest_data.html:18 +msgid "From" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:19 +msgid "To" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:27 +#, python-format +msgid "Latest vote: %s" +msgstr "Апошняя адзнака: %s" + +#: kallithea/templates/pullrequests/pullrequest_data.html:29 +msgid "Nobody voted" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:34 +#, python-format +msgid "You voted: %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:36 +msgid "You didn't vote" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:45 +msgid "Delete Pull Request" +msgstr "Выдаліць pull-запыт" + +#: kallithea/templates/pullrequests/pullrequest_data.html:46 +msgid "Confirm to delete this pull request" +msgstr "Пацвердзіце выдаленне гэтага pull-request'а" + +#: kallithea/templates/pullrequests/pullrequest_data.html:54 +msgid "(no title)" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:56 +#: kallithea/templates/pullrequests/pullrequest_show.html:31 +#: kallithea/templates/pullrequests/pullrequest_show.html:83 +msgid "Closed" +msgstr "Зачынена" + +#: kallithea/templates/pullrequests/pullrequest_show.html:6 +#, python-format +msgid "%s Pull Request #%s" +msgstr "%s Pull-запыт #%s" + +#: kallithea/templates/pullrequests/pullrequest_show.html:10 +#, python-format +msgid "Pull request #%s from %s#%s" +msgstr "Pull-запыты №%s ад %s#%s" + +#: kallithea/templates/pullrequests/pullrequest_show.html:57 +msgid "Summarize the changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:74 +msgid "Reviewer voting result" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:80 +#: kallithea/templates/pullrequests/pullrequest_show.html:81 +msgid "Pull request status calculated from votes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:94 +msgid "Still not reviewed by" +msgstr "Яшчэ не разгледжаны" + +#: kallithea/templates/pullrequests/pullrequest_show.html:98 +#, python-format +msgid "%d reviewer" +msgid_plural "%d reviewers" +msgstr[0] "%d рэцэнзент" +msgstr[1] "%d рэцэнзента" +msgstr[2] "%d рэцэнзентаў" + +#: kallithea/templates/pullrequests/pullrequest_show.html:100 +msgid "Pull request was reviewed by all reviewers" +msgstr "Запыт на занясенне змен быў разгледжаны ўсімі рэцэнзентамі" + +#: kallithea/templates/pullrequests/pullrequest_show.html:102 +msgid "There are no reviewers" +msgstr "Няма рэцэнзентаў" + +#: kallithea/templates/pullrequests/pullrequest_show.html:108 +msgid "Origin" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:114 +msgid "on" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:121 +msgid "Target" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:132 +msgid "Pull changes" +msgstr "Прыняць змены" + +#: kallithea/templates/pullrequests/pullrequest_show.html:155 +msgid "Created by" +msgstr "Створана" + +#: kallithea/templates/pullrequests/pullrequest_show.html:170 +msgid "Update" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:188 +msgid "Current revision - no change" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:224 +msgid "owner" +msgstr "уладальнік" + +#: kallithea/templates/pullrequests/pullrequest_show.html:224 +msgid "reviewer" +msgstr "рэцэнзент" + +#: kallithea/templates/pullrequests/pullrequest_show.html:227 +msgid "Remove reviewer" +msgstr "Выдаліць рэцэнзента" + +#: kallithea/templates/pullrequests/pullrequest_show.html:247 +msgid "Potential Reviewers" +msgstr "Патэнцыйныя рэцэнзенты" + +#: kallithea/templates/pullrequests/pullrequest_show.html:250 +msgid "Click to add the repository owner as reviewer:" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:273 +msgid "Save Changes" +msgstr "Захаваць змены" + +#: kallithea/templates/pullrequests/pullrequest_show.html:274 +msgid "Save as New Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:275 +msgid "Cancel Changes" +msgstr "Адмяніць змены" + +#: kallithea/templates/pullrequests/pullrequest_show.html:285 +msgid "Pull Request Content" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:4 +#, python-format +msgid "%s Pull Requests" +msgstr "%s Запыты на занясенне змен" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:9 +#, python-format +msgid "Pull Requests from %s'" +msgstr "Pull-запыты ад %s" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:11 +#, python-format +msgid "Pull Requests to '%s'" +msgstr "Pull-запыты для %s" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:35 +#, python-format +msgid "Show Pull Requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:37 +#, python-format +msgid "Show Pull Requests from '%s'" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:47 +#: kallithea/templates/pullrequests/pullrequest_show_my.html:26 +msgid "Hide closed pull requests (only show open pull requests)" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:49 +#: kallithea/templates/pullrequests/pullrequest_show_my.html:28 +msgid "Show closed pull requests (in addition to open pull requests)" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_my_data.html:3 +msgid "Pull Requests Created by Me" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_my_data.html:6 +msgid "Pull Requests I Participate In" +msgstr "" + +#: kallithea/templates/search/search.html:6 +#, python-format +msgid "%s Search" +msgstr "" + +#: kallithea/templates/search/search.html:8 +#: kallithea/templates/search/search.html:16 +msgid "Search in All Repositories" +msgstr "Пошук па ўсіх рэпазітарах" + +#: kallithea/templates/search/search.html:50 +msgid "Search term" +msgstr "Фраза для пошуку" + +#: kallithea/templates/search/search.html:62 +msgid "Search in" +msgstr "Крытэр пошуку" + +#: kallithea/templates/search/search.html:65 +msgid "File contents" +msgstr "Змесціва файлаў" + +#: kallithea/templates/search/search.html:66 +msgid "Commit messages" +msgstr "Паведамленні камітаў" + +#: kallithea/templates/search/search.html:67 +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:16 +#: kallithea/templates/summary/summary.html:39 +#, python-format +msgid "%s ATOM feed" +msgstr "ATOM стужка рэпазітара %s" + +#: kallithea/templates/summary/statistics.html:17 +#: kallithea/templates/summary/summary.html:40 +#, python-format +msgid "%s RSS feed" +msgstr "RSS стужка рэпазітара %s" + +#: kallithea/templates/summary/statistics.html:36 +#: kallithea/templates/summary/summary.html:103 +#: kallithea/templates/summary/summary.html:119 +msgid "Enable" +msgstr "Уключана" + +#: kallithea/templates/summary/statistics.html:39 +msgid "Stats gathered: " +msgstr "Атрыманая статыстыка: " + +#: kallithea/templates/summary/statistics.html:88 +#: kallithea/templates/summary/summary.html:352 +msgid "files" +msgstr "файлы" + +#: kallithea/templates/summary/statistics.html:112 +#: kallithea/templates/summary/summary.html:376 +msgid "Show more" +msgstr "Паказаць яшчэ" + +#: kallithea/templates/summary/statistics.html:389 +msgid "commits" +msgstr "commit'ы" + +#: kallithea/templates/summary/statistics.html:390 +msgid "files added" +msgstr "файлы дададзены" + +#: kallithea/templates/summary/statistics.html:391 +msgid "files changed" +msgstr "файлы зменены" + +#: kallithea/templates/summary/statistics.html:392 +msgid "files removed" +msgstr "файлы выдалены" + +#: kallithea/templates/summary/statistics.html:394 +msgid "commit" +msgstr "commit" + +#: kallithea/templates/summary/statistics.html:395 +msgid "file added" +msgstr "файл выдалены" + +#: kallithea/templates/summary/statistics.html:396 +msgid "file changed" +msgstr "файл зменены" + +#: kallithea/templates/summary/statistics.html:397 +msgid "file removed" +msgstr "файл выдалены" + +#: kallithea/templates/summary/summary.html:4 +#, python-format +msgid "%s Summary" +msgstr "%s агульныя звесткі" + +#: kallithea/templates/summary/summary.html:13 +#, python-format +msgid "Repository locked by %s" +msgstr "Рэпазітар заблакаваны %s" + +#: kallithea/templates/summary/summary.html:15 +msgid "Repository unlocked" +msgstr "Рэпазітар разблакаваны" + +#: kallithea/templates/summary/summary.html:22 +msgid "Fork of" +msgstr "Форк ад" + +#: kallithea/templates/summary/summary.html:77 +msgid "Show by Name" +msgstr "Паказаць па імі" + +#: kallithea/templates/summary/summary.html:78 +msgid "Show by ID" +msgstr "Паказаць па ID" + +#: kallithea/templates/summary/summary.html:95 +msgid "Trending files" +msgstr "Папулярныя файлы" + +#: kallithea/templates/summary/summary.html:111 +msgid "Download" +msgstr "Запампаваць" + +#: kallithea/templates/summary/summary.html:115 +msgid "There are no downloads yet" +msgstr "Спамповак яшчэ няма" + +#: kallithea/templates/summary/summary.html:117 +msgid "Downloads are disabled for this repository" +msgstr "Спампоўка адключана ў гэтым рэпазітары" + +#: kallithea/templates/summary/summary.html:123 +msgid "Download as zip" +msgstr "Запампаваць у zip" + +#: kallithea/templates/summary/summary.html:128 +msgid "Check this to download archive with subrepos" +msgstr "Адзначце для спампоўкі архіва з даччынымі рэпазітарамі" + +#: kallithea/templates/summary/summary.html:128 +msgid "with subrepos" +msgstr "з даччынымі рэпазітарамі" + +#: kallithea/templates/summary/summary.html:159 +msgid "Repository Size" +msgstr "Памер рэпазітара" + +#: kallithea/templates/summary/summary.html:166 +#: kallithea/templates/summary/summary.html:168 +msgid "Feed" +msgstr "Стужка навін" + +#: kallithea/templates/summary/summary.html:189 +msgid "Latest Changes" +msgstr "Апошнія змены" + +#: kallithea/templates/summary/summary.html:191 +msgid "Quick Start" +msgstr "Хуткі старт" + +#: kallithea/templates/summary/summary.html:205 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:296 +#, python-format +msgid "Download %s as %s" +msgstr "Запампаваць %s як %s" + +#: kallithea/templates/tags/tags.html:5 +#, python-format +msgid "%s Tags" +msgstr "%s Пазнак" + +#: kallithea/templates/tags/tags.html:26 +msgid "Compare Tags" +msgstr "Параўнаць тэгі" diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/i18n/hu/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/hu/LC_MESSAGES/kallithea.po Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/i18n/hu/LC_MESSAGES/kallithea.po Thu May 07 16:24:29 2015 +0200 @@ -8,14 +8,16 @@ "Project-Id-Version: Kallithea\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" "POT-Creation-Date: 2015-04-01 03:17+0200\n" -"PO-Revision-Date: 2014-07-02 19:08-0400\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2015-04-11 00:59+0200\n" +"Last-Translator: Balázs Úr \n" +"Language-Team: Hungarian " +"\n" +"Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: hu\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 2.3-dev\n" #: kallithea/controllers/changelog.py:86 #: kallithea/controllers/pullrequests.py:247 kallithea/lib/base.py:449 @@ -55,9 +57,8 @@ #: kallithea/controllers/changeset.py:352 #: kallithea/controllers/pullrequests.py:699 -#, fuzzy msgid "No comments." -msgstr "" +msgstr "Nincsenek hozzászólások." #: kallithea/controllers/changeset.py:382 msgid "" @@ -2351,11 +2352,11 @@ #: kallithea/templates/admin/admin.html:13 #: kallithea/templates/journal/journal.html:12 -#, fuzzy, python-format +#, python-format msgid "%s Entry" msgid_plural "%s Entries" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%s bejegyzés" +msgstr[1] "%s bejegyzés" #: kallithea/templates/admin/admin_log.html:6 #: kallithea/templates/admin/my_account/my_account_repos.html:50 @@ -3246,9 +3247,8 @@ msgstr "" #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:53 -#, fuzzy msgid "Confirm to delete this group" -msgstr "" +msgstr "A csoport törlésének megerősítése" #: kallithea/templates/admin/repo_groups/repo_group_show.html:4 #, python-format @@ -3335,9 +3335,9 @@ msgstr "" #: kallithea/templates/admin/repos/repo_edit.html:8 -#, fuzzy, python-format +#, python-format msgid "%s Repository Settings" -msgstr "" +msgstr "%s tároló beállítások" #: kallithea/templates/admin/repos/repo_edit.html:49 msgid "Extra Fields" @@ -3429,16 +3429,15 @@ msgstr "" #: kallithea/templates/admin/repos/repo_edit_advanced.html:82 -#, fuzzy msgid "Delete this Repository" -msgstr "" +msgstr "Tároló törlése" #: kallithea/templates/admin/repos/repo_edit_advanced.html:85 -#, fuzzy, python-format +#, python-format msgid "This repository has %s fork" msgid_plural "This repository has %s forks" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Ennek a tárolónak %s elágazása van" +msgstr[1] "Ennek a tárolónak %s elágazása van" #: kallithea/templates/admin/repos/repo_edit_advanced.html:86 msgid "Detach forks" @@ -4437,9 +4436,8 @@ msgstr "" #: kallithea/templates/base/root.html:22 -#, fuzzy msgid "Add Another Comment" -msgstr "" +msgstr "Egy másik hozzászólás hozzáadása" #: kallithea/templates/base/root.html:23 #: kallithea/templates/data_table/_dt_elements.html:216 @@ -4809,9 +4807,8 @@ msgstr "" #: kallithea/templates/changeset/changeset_file_comment.html:50 -#, fuzzy msgid "Delete comment?" -msgstr "" +msgstr "Hozzászólás törlése?" #: kallithea/templates/changeset/changeset_file_comment.html:67 msgid "Commenting on line {1}." @@ -4866,11 +4863,11 @@ msgstr[1] "" #: kallithea/templates/changeset/changeset_file_comment.html:115 -#, fuzzy, python-format +#, python-format msgid "%d inline" msgid_plural "%d inline" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d sorközi" +msgstr[1] "%d sorközi" #: kallithea/templates/changeset/changeset_file_comment.html:116 #, python-format @@ -4957,9 +4954,9 @@ msgstr "" #: kallithea/templates/compare/compare_cs.html:84 -#, fuzzy, python-format +#, python-format msgid "%s changesets" -msgstr "" +msgstr "%s módosításcsomag" #: kallithea/templates/compare/compare_cs.html:85 msgid "behind" @@ -5575,14 +5572,12 @@ msgstr "" #: kallithea/templates/pullrequests/pullrequest_show.html:227 -#, fuzzy msgid "Remove reviewer" -msgstr "" +msgstr "Átnéző eltávolítása" #: kallithea/templates/pullrequests/pullrequest_show.html:247 -#, fuzzy msgid "Potential Reviewers" -msgstr "" +msgstr "Lehetséges átnézők" #: kallithea/templates/pullrequests/pullrequest_show.html:250 msgid "Click to add the repository owner as reviewer:" @@ -5841,4 +5836,3 @@ #: kallithea/templates/tags/tags.html:26 msgid "Compare Tags" msgstr "" - diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/i18n/ru/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/ru/LC_MESSAGES/kallithea.po Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/i18n/ru/LC_MESSAGES/kallithea.po Thu May 07 16:24:29 2015 +0200 @@ -12,18 +12,20 @@ # SkryabinD , 2014 # softforwinxp , 2013 # zhmylove , 2013 +# Andrew Shadura , 2015 +# msgid "" msgstr "" "Project-Id-Version: Kallithea\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" "POT-Creation-Date: 2015-04-01 03:17+0200\n" -"PO-Revision-Date: 2015-04-01 13:08+0200\n" +"PO-Revision-Date: 2015-04-13 20:18+0200\n" "Last-Translator: Andrew Shadura \n" "Language-Team: Russian " "\n" "Language: ru\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" "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" @@ -84,7 +86,7 @@ #: kallithea/controllers/compare.py:255 msgid "Cannot compare repositories without using common ancestor" -msgstr "" +msgstr "Невозможно сравнивать репозитории без общего предка" #: kallithea/controllers/error.py:96 msgid "The request could not be understood by the server due to malformed syntax." @@ -221,7 +223,7 @@ #: kallithea/controllers/files.py:541 msgid "Empty repository" -msgstr "Пустой репозитарий" +msgstr "Пустой репозиторий" #: kallithea/controllers/files.py:543 msgid "Unknown archive type" @@ -357,12 +359,12 @@ #: kallithea/controllers/pullrequests.py:398 msgid "Missing changesets since the previous pull request:" -msgstr "" +msgstr "Отсутствующие ревизии относительно предыдущего pull-запроса:" #: kallithea/controllers/pullrequests.py:405 #, python-format msgid "New changesets on %s %s since the previous pull request:" -msgstr "" +msgstr "Новые ревизии на %s %s относительно предыдущего pull-запроса" #: kallithea/controllers/pullrequests.py:412 msgid "Ancestor didn't change - show diff since previous version:" @@ -373,17 +375,17 @@ msgid "" "This pull request is based on another %s revision and there is no simple " "diff." -msgstr "" +msgstr "Этот pull-запрос основан на другой ревизии %s, простой diff невозможен" #: kallithea/controllers/pullrequests.py:421 #, python-format msgid "No changes found on %s %s since previous version." -msgstr "" +msgstr "Нет изменений на %s %s относительно предыдущей версии." #: kallithea/controllers/pullrequests.py:456 #, python-format msgid "Closed, replaced by %s ." -msgstr "" +msgstr "Закрыт, замещён %s ." #: kallithea/controllers/pullrequests.py:464 msgid "Pull request update created" @@ -400,29 +402,29 @@ #: kallithea/controllers/pullrequests.py:577 #, python-format msgid "This pull request has already been merged to %s." -msgstr "" +msgstr "Этот pull-запрос уже принят на ветку %s." #: kallithea/controllers/pullrequests.py:579 msgid "This pull request has been closed and can not be updated." -msgstr "" +msgstr "Этот pull-запрос был закрыт и не может быть обновлён." #: kallithea/controllers/pullrequests.py:597 #, python-format msgid "This pull request can be updated with changes on %s:" -msgstr "" +msgstr "Этот pull-запрос может быть обновлён из %s:" #: kallithea/controllers/pullrequests.py:600 msgid "No changesets found for updating this pull request." -msgstr "" +msgstr "Нет изменений для обновления этого pull-запроса." #: kallithea/controllers/pullrequests.py:608 #, python-format msgid "Note: Branch %s has another head: %s." -msgstr "" +msgstr "Внимание: Ветка %s имеет ещё одну верхушку: %s." #: kallithea/controllers/pullrequests.py:614 msgid "Git pull requests don't support updates yet." -msgstr "" +msgstr "Обновление pull-запросы git не поддерживается." #: kallithea/controllers/pullrequests.py:701 msgid "Closing." @@ -521,12 +523,12 @@ #: kallithea/controllers/admin/gists.py:267 msgid "Successfully updated gist data" -msgstr "" +msgstr "Данные gist-записи обновлены" #: kallithea/controllers/admin/gists.py:270 #, python-format msgid "Error occurred during update of gist %s" -msgstr "" +msgstr "Произошла ошибка при обновлении gist-записи %s" #: kallithea/controllers/admin/my_account.py:70 msgid "You can't edit this user since it's crucial for entire application" @@ -571,17 +573,17 @@ #: kallithea/controllers/admin/my_account.py:254 #: kallithea/controllers/admin/users.py:314 msgid "Api key successfully created" -msgstr "" +msgstr "API-ключ успешно создан" #: kallithea/controllers/admin/my_account.py:266 #: kallithea/controllers/admin/users.py:330 msgid "Api key successfully reset" -msgstr "" +msgstr "API-ключ успешно сброшен" #: kallithea/controllers/admin/my_account.py:270 #: kallithea/controllers/admin/users.py:334 msgid "Api key successfully deleted" -msgstr "" +msgstr "API-ключ успешно удалён" #: kallithea/controllers/admin/permissions.py:63 #: kallithea/controllers/admin/permissions.py:67 @@ -805,7 +807,7 @@ #: kallithea/controllers/admin/repos.py:492 msgid "-- Not a fork --" -msgstr "" +msgstr "-- Не форк --" #: kallithea/controllers/admin/repos.py:526 msgid "Updated repository visibility in public journal" @@ -860,7 +862,7 @@ #: kallithea/controllers/admin/repos.py:622 msgid "Cache invalidation successful" -msgstr "" +msgstr "Кэш сброшен" #: kallithea/controllers/admin/repos.py:626 msgid "An error occurred during cache invalidation" @@ -1045,7 +1047,7 @@ #: kallithea/lib/base.py:427 msgid "Repository not found in the filesystem" -msgstr "" +msgstr "Репозиторий не найден на файловой системе" #: kallithea/lib/base.py:453 kallithea/lib/helpers.py:643 msgid "Changeset not found" @@ -2079,7 +2081,7 @@ #: kallithea/templates/about.html:4 kallithea/templates/about.html:17 msgid "About" -msgstr "" +msgstr "О программе" #: kallithea/templates/index.html:5 msgid "Dashboard" @@ -2316,7 +2318,7 @@ #: kallithea/templates/password_reset.html:35 #: kallithea/templates/register.html:79 msgid "Captcha" -msgstr "" +msgstr "Капча" #: kallithea/templates/password_reset.html:46 msgid "Send Password Reset Email" @@ -2331,12 +2333,12 @@ #: kallithea/templates/register.html:5 kallithea/templates/register.html:14 #: kallithea/templates/register.html:90 msgid "Sign Up" -msgstr "Вступить" +msgstr "Регистрация" #: kallithea/templates/register.html:12 #, python-format msgid "Sign Up to %s" -msgstr "" +msgstr "Регистра на %s" #: kallithea/templates/register.html:42 msgid "Re-enter password" @@ -2372,7 +2374,7 @@ #: kallithea/templates/register.html:94 msgid "Please wait for an administrator to activate your account." -msgstr "" +msgstr "Пожалуйста, подождите, пока администратор подтвердит Вашу регистрацию." #: kallithea/templates/switch_to_list.html:10 #: kallithea/templates/branches/branches_data.html:69 @@ -2433,7 +2435,7 @@ #: kallithea/templates/admin/admin_log.html:7 #: kallithea/templates/admin/permissions/permissions_globals.html:18 msgid "Repository" -msgstr "Репозитарий" +msgstr "Репозиторий" #: kallithea/templates/admin/admin_log.html:8 #: kallithea/templates/bookmarks/bookmarks.html:51 @@ -2485,12 +2487,12 @@ #: kallithea/templates/admin/auth/auth_settings.html:40 #: kallithea/templates/base/root.html:40 msgid "enabled" -msgstr "" +msgstr "включено" #: kallithea/templates/admin/auth/auth_settings.html:40 #: kallithea/templates/base/root.html:41 msgid "disabled" -msgstr "" +msgstr "отключено" #: kallithea/templates/admin/auth/auth_settings.html:51 msgid "Plugin" @@ -2556,7 +2558,7 @@ #: kallithea/templates/admin/defaults/defaults.html:59 #: kallithea/templates/admin/repos/repo_edit_settings.html:95 msgid "Enable statistics window on summary page." -msgstr "Включить окно статистики на странице 'Общие сведения'." +msgstr "Включить окно статистики на странице «Общие сведения»." #: kallithea/templates/admin/defaults/defaults.html:65 #: kallithea/templates/admin/repos/repo_edit_settings.html:100 @@ -2566,7 +2568,7 @@ #: kallithea/templates/admin/defaults/defaults.html:69 #: kallithea/templates/admin/repos/repo_edit_settings.html:104 msgid "Enable download menu on summary page." -msgstr "Включить меню скачивания на странице 'Общие сведения'." +msgstr "Включить меню скачивания на странице «Общие сведения»." #: kallithea/templates/admin/defaults/defaults.html:75 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:34 @@ -2582,7 +2584,7 @@ #: kallithea/templates/admin/gists/edit.html:5 #: kallithea/templates/admin/gists/edit.html:18 msgid "Edit Gist" -msgstr "" +msgstr "Правка gist-записи" #: kallithea/templates/admin/gists/edit.html:36 #, python-format @@ -2622,7 +2624,7 @@ #: kallithea/templates/admin/gists/edit.html:145 msgid "Update Gist" -msgstr "" +msgstr "Обновить" #: kallithea/templates/admin/gists/edit.html:146 #: kallithea/templates/changeset/changeset_file_comment.html:89 @@ -2633,24 +2635,24 @@ #: kallithea/templates/admin/gists/index.html:16 #, python-format msgid "Private Gists for User %s" -msgstr "Приватная запись Gist для пользователя %s" +msgstr "Приватная gist-запись для пользователя %s" #: kallithea/templates/admin/gists/index.html:8 #: kallithea/templates/admin/gists/index.html:18 #, python-format msgid "Public Gists for User %s" -msgstr "Публичная запись Gist для пользователя %s" +msgstr "Публичная gist-запись для пользователя %s" #: kallithea/templates/admin/gists/index.html:10 #: kallithea/templates/admin/gists/index.html:20 msgid "Public Gists" -msgstr "Публичные записи Gist" +msgstr "Публичные gist-записи" #: kallithea/templates/admin/gists/index.html:37 #: kallithea/templates/admin/gists/show.html:25 #: kallithea/templates/base/base.html:240 msgid "Create New Gist" -msgstr "" +msgstr "Создать новую gist-запись" #: kallithea/templates/admin/gists/index.html:54 #: kallithea/templates/data_table/_dt_elements.html:143 @@ -2659,7 +2661,7 @@ #: kallithea/templates/admin/gists/index.html:74 msgid "There are no gists yet" -msgstr "Записи Gist отсутствуют" +msgstr "Gist-записи отсутствуют" #: kallithea/templates/admin/gists/new.html:5 #: kallithea/templates/admin/gists/new.html:18 @@ -2737,7 +2739,7 @@ #: kallithea/templates/admin/gists/show.html:56 msgid "Confirm to delete this Gist" -msgstr "" +msgstr "Подтвердите удаление этой gist-записи" #: kallithea/templates/admin/gists/show.html:63 #: kallithea/templates/changeset/changeset_file_comment.html:91 @@ -2755,16 +2757,16 @@ #: kallithea/templates/files/files_edit.html:49 #: kallithea/templates/files/files_source.html:34 msgid "Show as Raw" -msgstr "" +msgstr "Показать только текст" #: kallithea/templates/admin/gists/show.html:73 msgid "created" -msgstr "создал" +msgstr "создана" #: kallithea/templates/admin/gists/show.html:86 #: kallithea/templates/files/files_source.html:73 msgid "Show as raw" -msgstr "Показать без форматирования" +msgstr "Показать только текст" #: kallithea/templates/admin/my_account/my_account.html:5 #: kallithea/templates/admin/my_account/my_account.html:9 @@ -2780,11 +2782,11 @@ #: kallithea/templates/admin/my_account/my_account.html:37 #: kallithea/templates/admin/users/user_edit.html:30 msgid "API Keys" -msgstr "" +msgstr "API-ключи" #: kallithea/templates/admin/my_account/my_account.html:38 msgid "My Emails" -msgstr "Мои Email-ы" +msgstr "Мои адреса E-mail" #: kallithea/templates/admin/my_account/my_account.html:39 msgid "My Repositories" @@ -2817,7 +2819,7 @@ #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #, python-format msgid "Confirm to reset this api key: %s" -msgstr "" +msgstr "Подтвердите сброс этого API-ключа: %s" #: kallithea/templates/admin/my_account/my_account_api_keys.html:15 #: kallithea/templates/admin/users/user_edit_api_keys.html:15 @@ -2833,7 +2835,7 @@ #: kallithea/templates/admin/users/user_edit_api_keys.html:40 #, python-format msgid "Confirm to remove this api key: %s" -msgstr "" +msgstr "Подтвердите удаление этого API-ключа: %s" #: kallithea/templates/admin/my_account/my_account_api_keys.html:42 #: kallithea/templates/admin/users/user_edit_api_keys.html:42 @@ -2901,7 +2903,7 @@ #: kallithea/templates/admin/my_account/my_account_password.html:7 msgid "Current password" -msgstr "" +msgstr "Текущий пароль" #: kallithea/templates/admin/my_account/my_account_password.html:16 #: kallithea/templates/admin/users/user_edit_profile.html:69 @@ -2910,7 +2912,7 @@ #: kallithea/templates/admin/my_account/my_account_password.html:25 msgid "Confirm new password" -msgstr "" +msgstr "Подтвердите новый пароль" #: kallithea/templates/admin/my_account/my_account_profile.html:11 msgid "Change your avatar at" @@ -2933,7 +2935,7 @@ #: kallithea/templates/admin/my_account/my_account_profile.html:16 #: kallithea/templates/admin/users/user_edit_profile.html:15 msgid "current IP" -msgstr "" +msgstr "текущий IP-адрес" #: kallithea/templates/admin/my_account/my_account_profile.html:28 msgid "" @@ -3039,9 +3041,8 @@ "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 @@ -3064,8 +3065,8 @@ "will be lost" msgstr "" "Выбранные привилегии будут установлены по умолчанию для каждой группы " -"репозиториев. Учтите, что ранее установленные привилегии по умолчанию для" -" групп репозиториев будут сброшены" +"репозиториев. Учтите, что ранее установленные привилегии по умолчанию для " +"групп репозиториев будут сброшены" #: kallithea/templates/admin/permissions/permissions_globals.html:46 #: kallithea/templates/data_table/_dt_elements.html:211 @@ -3079,8 +3080,8 @@ "will be lost" msgstr "" "Выбранные привилегии будут установлены по умолчанию для каждой группы " -"пользователей. Учтите, что ранее установленные привилегии по умолчанию " -"для групп пользователей будут сброшены" +"пользователей. Учтите, что ранее установленные привилегии по умолчанию для " +"групп пользователей будут сброшены" #: kallithea/templates/admin/permissions/permissions_globals.html:60 msgid "Repository creation" @@ -3120,7 +3121,7 @@ #: kallithea/templates/admin/users/user_edit_ips.html:23 #, python-format msgid "Confirm to delete this ip: %s" -msgstr "Подтвердите удаление ip %s" +msgstr "Подтвердите удаление IP %s" #: kallithea/templates/admin/permissions/permissions_ips.html:21 #: kallithea/templates/admin/users/user_edit_ips.html:30 @@ -3130,11 +3131,11 @@ #: kallithea/templates/admin/permissions/permissions_ips.html:32 #: kallithea/templates/admin/users/user_edit_ips.html:42 msgid "New ip address" -msgstr "Новый ip-адрес" +msgstr "Новый IP-адрес" #: kallithea/templates/admin/permissions/permissions_perms.html:1 msgid "Default User Permissions Overview" -msgstr "Обзор прав пользователей по-умолчанию" +msgstr "Обзор прав пользователей по умолчанию" #: kallithea/templates/admin/repo_groups/repo_group_add.html:11 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:11 @@ -3169,7 +3170,7 @@ #: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 #, python-format msgid "%s Repository Group Settings" -msgstr "Настройки рруппы репозиториев %s" +msgstr "Настройки группы репозиториев %s" #: kallithea/templates/admin/repo_groups/repo_group_edit.html:21 msgid "Add Child Group" @@ -3228,7 +3229,7 @@ #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 msgid "Delete this repository group" -msgstr "" +msgstr "Удалить эту группу репозиториев" #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8 @@ -3271,7 +3272,7 @@ #: 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 "по-умолчанию" +msgstr "по умолчанию" #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71 @@ -3312,7 +3313,7 @@ "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_edit_settings.html:53 @@ -3361,7 +3362,8 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:76 #: kallithea/templates/forks/fork.html:42 msgid "Keep it short and to the point. Use a README file for longer descriptions." -msgstr "Короткое и осмысленное. Для развернутого описания используйте файл README." +msgstr "" +"Короткое и осмысленное. Для развернутого описания используйте файл README." #: kallithea/templates/admin/repos/repo_add_base.html:45 #: kallithea/templates/admin/repos/repo_edit_settings.html:46 @@ -4963,7 +4965,7 @@ msgstr[2] "%d к строкам" #: kallithea/templates/changeset/changeset_file_comment.html:116 -#, fuzzy, python-format +#, python-format msgid "%d general" msgid_plural "%d general" msgstr[0] "" diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/lib/dbmigrate/schema/db_2_2_0.py --- a/kallithea/lib/dbmigrate/schema/db_2_2_0.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/lib/dbmigrate/schema/db_2_2_0.py Thu May 07 16:24:29 2015 +0200 @@ -1239,7 +1239,7 @@ pass return get_clone_url(uri_tmpl=uri_tmpl, - qualifed_home_url=qualified_home_url, + qualified_home_url=qualified_home_url, repo_name=self.repo_name, repo_id=self.repo_id, **override) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/lib/dbmigrate/schema/db_2_2_3.py --- a/kallithea/lib/dbmigrate/schema/db_2_2_3.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/lib/dbmigrate/schema/db_2_2_3.py Thu May 07 16:24:29 2015 +0200 @@ -1263,7 +1263,7 @@ pass return get_clone_url(uri_tmpl=uri_tmpl, - qualifed_home_url=qualified_home_url, + qualified_home_url=qualified_home_url, repo_name=self.repo_name, repo_id=self.repo_id, **override) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/lib/helpers.py --- a/kallithea/lib/helpers.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/lib/helpers.py Thu May 07 16:24:29 2015 +0200 @@ -423,7 +423,7 @@ #============================================================================== 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 +from kallithea.model.db import User, ChangesetStatus, PullRequest age = lambda x, y=False: _age(x, y) capitalize = lambda x: x.capitalize() @@ -736,12 +736,15 @@ def get_pull_request(): pull_request_id = action_params + nice_id = PullRequest.make_nice_id(pull_request_id) + deleted = user_log.repository is None if deleted: repo_name = user_log.repository_name else: repo_name = user_log.repository.repo_name - return link_to(_('Pull request #%s') % pull_request_id, + + return link_to(_('Pull request %s') % nice_id, url('pullrequest_show', repo_name=repo_name, pull_request_id=pull_request_id)) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/lib/paster_commands/make_rcextensions.py --- a/kallithea/lib/paster_commands/make_rcextensions.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/lib/paster_commands/make_rcextensions.py Thu May 07 16:24:29 2015 +0200 @@ -30,7 +30,6 @@ import os import sys -import logging import pkg_resources from kallithea.lib.utils import BasePasterCommand, ask_ok @@ -40,46 +39,44 @@ rc_path = dn(dn(dn(os.path.realpath(__file__)))) sys.path.append(rc_path) -log = logging.getLogger(__name__) - class Command(BasePasterCommand): max_args = 1 min_args = 1 - usage = "CONFIG_FILE" group_name = "Kallithea" takes_config_file = -1 parser = BasePasterCommand.standard_parser(verbose=True) - summary = "Creates additional extensions for kallithea" + summary = "Write template file for extending Kallithea in Python." + usage = "CONFIG_FILE" + description = '''\ + A rcextensions directory with a __init__.py file will be created next to + the ini file. Local customizations in that file will survive upgrades. + The file contains instructions on how it can be customized. + ''' def command(self): - logging.config.fileConfig(self.path_to_ini_file) from pylons import config - def _make_file(ext_file, tmpl): - bdir = os.path.split(ext_file)[0] - if not os.path.isdir(bdir): - os.makedirs(bdir) - with open(ext_file, 'wb') as f: - f.write(tmpl) - log.info('Writen new extensions file to %s' % ext_file) - here = config['here'] - tmpl = pkg_resources.resource_string( + content = pkg_resources.resource_string( 'kallithea', os.path.join('config', 'rcextensions', '__init__.py') ) ext_file = os.path.join(here, 'rcextensions', '__init__.py') if os.path.exists(ext_file): msg = ('Extension file already exists, do you want ' 'to overwrite it ? [y/n]') - if ask_ok(msg): - _make_file(ext_file, tmpl) - else: - log.info('nothing done...') - else: - _make_file(ext_file, tmpl) + if not ask_ok(msg): + print 'Nothing done...' + return + + dirname = os.path.dirname(ext_file) + if not os.path.isdir(dirname): + os.makedirs(dirname) + with open(ext_file, 'wb') as f: + f.write(content) + print 'Wrote new extensions file to %s' % ext_file def update_parser(self): pass diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/lib/utils2.py --- a/kallithea/lib/utils2.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/lib/utils2.py Thu May 07 16:24:29 2015 +0200 @@ -503,8 +503,8 @@ return ''.join(uri) -def get_clone_url(uri_tmpl, qualifed_home_url, repo_name, repo_id, **override): - parsed_url = urlobject.URLObject(qualifed_home_url) +def get_clone_url(uri_tmpl, qualified_home_url, repo_name, repo_id, **override): + parsed_url = urlobject.URLObject(qualified_home_url) decoded_path = safe_unicode(urllib.unquote(parsed_url.path.rstrip('/'))) args = { 'scheme': parsed_url.scheme, @@ -625,25 +625,25 @@ def _extract_extras(env=None): """ - Extracts the rc extras data from os.environ, and wraps it into named + Extracts the Kallithea extras data from os.environ, and wraps it into named AttributeDict object """ if not env: env = os.environ try: - rc_extras = json.loads(env['KALLITHEA_EXTRAS']) + extras = json.loads(env['KALLITHEA_EXTRAS']) except KeyError: - rc_extras = {} + extras = {} try: for k in ['username', 'repository', 'locked_by', 'scm', 'make_lock', 'action', 'ip']: - rc_extras[k] + extras[k] except KeyError, e: - raise Exception('Missing key %s in os.environ %s' % (e, rc_extras)) + raise Exception('Missing key %s in os.environ %s' % (e, extras)) - return AttributeDict(rc_extras) + return AttributeDict(extras) def _set_extras(extras): diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/lib/vcs/backends/hg/repository.py --- a/kallithea/lib/vcs/backends/hg/repository.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/lib/vcs/backends/hg/repository.py Thu May 07 16:24:29 2015 +0200 @@ -229,7 +229,7 @@ def _get_all_revisions(self): - return map(lambda x: hex(x[7]), self._repo.changelog.index)[:-1] + return [self._repo[x].hex() for x in self._repo.filtered('visible').changelog.revs()] def get_diff(self, rev1, rev2, path='', ignore_whitespace=False, context=3): @@ -264,6 +264,7 @@ return ''.join(patch.diff(self._repo, rev1, rev2, match=file_filter, opts=diffopts(git=True, + showfunc=True, ignorews=ignore_whitespace, context=context))) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/lib/vcs/utils/lazy.py --- a/kallithea/lib/vcs/utils/lazy.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/lib/vcs/utils/lazy.py Thu May 07 16:24:29 2015 +0200 @@ -1,3 +1,6 @@ +import threading + + class _Missing(object): def __repr__(self): @@ -41,8 +44,6 @@ obj.__dict__[self.__name__] = value return value -import threading - class ThreadLocalLazyProperty(LazyProperty): """ diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/model/changeset_status.py --- a/kallithea/model/changeset_status.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/model/changeset_status.py Thu May 07 16:24:29 2015 +0200 @@ -66,9 +66,27 @@ q = q.order_by(ChangesetStatus.version.asc()) return q + def _calculate_status(self, statuses): + """ + Given a list of statuses, calculate the resulting status, according to + the policy: approve if consensus, reject when at least one reject. + """ + + if not statuses: + return ChangesetStatus.STATUS_UNDER_REVIEW + + if all(st and st.status == ChangesetStatus.STATUS_APPROVED for st in statuses): + return ChangesetStatus.STATUS_APPROVED + + if any(st and st.status == ChangesetStatus.STATUS_REJECTED for st in statuses): + return ChangesetStatus.STATUS_REJECTED + + return ChangesetStatus.STATUS_UNDER_REVIEW + def calculate_pull_request_result(self, pull_request): """ - Policy: approve if consensus. Only approve and reject counts as valid votes. + Return a tuple (reviewers, pending reviewers, pull request status) + Only approve and reject counts as valid votes. """ # collect latest votes from all voters @@ -77,24 +95,21 @@ pull_request=pull_request, with_revisions=True)): cs_statuses[st.author.username] = st + # collect votes from official reviewers pull_request_reviewers = [] pull_request_pending_reviewers = [] - approved_votes = 0 + relevant_statuses = [] for r in pull_request.reviewers: st = cs_statuses.get(r.user.username) - if st and st.status == ChangesetStatus.STATUS_APPROVED: - approved_votes += 1 + relevant_statuses.append(st) if not st or st.status in (ChangesetStatus.STATUS_NOT_REVIEWED, ChangesetStatus.STATUS_UNDER_REVIEW): st = None pull_request_pending_reviewers.append(r.user) pull_request_reviewers.append((r.user, st)) - # calculate result - result = ChangesetStatus.STATUS_UNDER_REVIEW - if approved_votes and approved_votes == len(pull_request.reviewers): - result = ChangesetStatus.STATUS_APPROVED + result = self._calculate_status(relevant_statuses) return (pull_request_reviewers, pull_request_pending_reviewers, diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/model/comment.py --- a/kallithea/model/comment.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/model/comment.py Thu May 07 16:24:29 2015 +0200 @@ -63,10 +63,6 @@ line_no=None, revision=None, pull_request=None, status_change=None, closing_pr=False): """ - Get notification data - - :param comment_text: - :param line: :returns: tuple (subj,body,recipients,notification_type,email_kwargs) """ # make notification @@ -130,9 +126,9 @@ comment_url = pull_request.url(canonical=True, anchor='comment-%s' % comment.comment_id) subj = safe_unicode( - h.link_to('Re pull request #%(pr_id)s: %(desc)s %(line)s' % \ + h.link_to('Re pull request %(pr_nice_id)s: %(desc)s %(line)s' % \ {'desc': desc, - 'pr_id': comment.pull_request.pull_request_id, + 'pr_nice_id': comment.pull_request.nice_id(), 'line': line}, comment_url) ) @@ -148,7 +144,7 @@ #set some variables for email notification email_kwargs = { 'pr_title': pull_request.title, - 'pr_id': pull_request.pull_request_id, + 'pr_nice_id': pull_request.nice_id(), 'status_change': status_change, 'closing_pr': closing_pr, 'pr_comment_url': comment_url, @@ -167,22 +163,12 @@ f_path=None, line_no=None, status_change=None, closing_pr=False, send_email=True): """ - Creates new comment for changeset or pull request. - If status_change is not None this comment is associated with a - status change of changeset or changesets associated with pull request + Creates a new comment for either a changeset or a pull request. + status_change and closing_pr is only for the optional email. - :param text: - :param repo: - :param user: - :param revision: - :param pull_request: (for emails, not for comments) - :param f_path: - :param line_no: - :param status_change: (for emails, not for comments) - :param closing_pr: (for emails, not for comments) - :param send_email: also send email + Returns the created comment. """ - if not text: + if not status_change and not text: log.warning('Missing text for comment, skipping...') return @@ -239,11 +225,6 @@ return comment def delete(self, comment): - """ - Deletes given comment - - :param comment_id: - """ comment = self.__get_changeset_comment(comment) Session().delete(comment) @@ -251,33 +232,40 @@ def get_comments(self, repo_id, revision=None, pull_request=None): """ - Gets main comments based on revision or pull_request_id - - :param repo_id: - :param revision: - :param pull_request: - """ + Gets general comments for either revision or pull_request. - q = ChangesetComment.query()\ - .filter(ChangesetComment.repo_id == repo_id)\ - .filter(ChangesetComment.line_no == None)\ - .filter(ChangesetComment.f_path == None) - if revision: - q = q.filter(ChangesetComment.revision == revision) - elif pull_request: - pull_request = self.__get_pull_request(pull_request) - q = q.filter(ChangesetComment.pull_request == pull_request) - else: - raise Exception('Please specify revision or pull_request') - q = q.order_by(ChangesetComment.created_on) - return q.all() + Returns a list, ordered by creation date. + """ + return self._get_comments(repo_id, revision=revision, pull_request=pull_request, + inline=False) def get_inline_comments(self, repo_id, revision=None, pull_request=None): + """ + Gets inline comments for either revision or pull_request. + + Returns a list of tuples with file path and list of comments per line number. + """ + comments = self._get_comments(repo_id, revision=revision, pull_request=pull_request, + inline=True) + + paths = defaultdict(lambda: defaultdict(list)) + for co in comments: + paths[co.f_path][co.line_no].append(co) + return paths.items() + + def _get_comments(self, repo_id, revision=None, pull_request=None, inline=False): + """ + Gets comments for either revision or pull_request_id, either inline or general. + """ q = Session().query(ChangesetComment)\ - .filter(ChangesetComment.repo_id == repo_id)\ - .filter(ChangesetComment.line_no != None)\ - .filter(ChangesetComment.f_path != None)\ - .order_by(ChangesetComment.comment_id.asc())\ + .filter(ChangesetComment.repo_id == repo_id) + + if inline: + q = q.filter(ChangesetComment.line_no != None)\ + .filter(ChangesetComment.f_path != None) + else: + q = q.filter(ChangesetComment.line_no == None)\ + .filter(ChangesetComment.f_path == None) if revision: q = q.filter(ChangesetComment.revision == revision) @@ -285,12 +273,6 @@ pull_request = self.__get_pull_request(pull_request) q = q.filter(ChangesetComment.pull_request == pull_request) else: - raise Exception('Please specify revision or pull_request_id') - - comments = q.all() + raise Exception('Please specify either revision or pull_request') - paths = defaultdict(lambda: defaultdict(list)) - - for co in comments: - paths[co.f_path][co.line_no].append(co) - return paths.items() + return q.order_by(ChangesetComment.created_on).all() diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/model/db.py --- a/kallithea/model/db.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/model/db.py Thu May 07 16:24:29 2015 +0200 @@ -175,8 +175,8 @@ } 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_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + app_settings_name = Column(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) @@ -338,11 +338,11 @@ 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) + ui_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + ui_section = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_key = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_value = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + ui_active = Column(Boolean(), nullable=True, unique=None, default=True) # def __init__(self, section='', key='', value=''): # self.ui_section = section @@ -401,20 +401,20 @@ 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) + user_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + username = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + password = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + active = Column(Boolean(), nullable=True, unique=None, default=True) + admin = Column(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) + lastname = Column(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) + last_login = Column(DateTime(timezone=False), nullable=True, unique=None, default=None) + extern_type = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + extern_name = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + api_key = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + inherit_default_permissions = Column(Boolean(), nullable=False, unique=None, default=True) + created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) _user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data user_log = relationship('UserLog') @@ -675,12 +675,12 @@ ) __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_api_key_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + api_key = Column(String(255, convert_unicode=False), nullable=False, unique=True) + description = Column(UnicodeText(1024)) + expires = Column(Float(53), nullable=False) + created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) user = relationship('User') @@ -701,8 +701,8 @@ ) __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_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column(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') @@ -732,10 +732,10 @@ ) __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) + ip_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + ip_addr = Column(String(255, convert_unicode=False), nullable=True, unique=False, default=None) + active = Column(Boolean(), nullable=True, unique=None, default=True) user = relationship('User') @classmethod @@ -760,14 +760,14 @@ {'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) + user_log_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + username = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + repository_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=True) + repository_name = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + user_ip = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + action = Column(UnicodeText(1200000, convert_unicode=False), nullable=True, unique=None, default=None) + action_date = Column(DateTime(timezone=False), nullable=True, unique=None, default=None) def __unicode__(self): return u"<%s('id:%s:%s')>" % (self.__class__.__name__, @@ -789,13 +789,13 @@ '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) + users_group_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_name = Column(String(255, convert_unicode=False), nullable=False, unique=True, default=None) + user_group_description = Column(String(10000, convert_unicode=False), nullable=True, unique=None, default=None) + users_group_active = Column(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) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column(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-orphan") @@ -879,9 +879,9 @@ '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) + users_group_member_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column(Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) user = relationship('User') users_group = relationship('UserGroup') @@ -900,14 +900,14 @@ ) 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(255), nullable=False, unique=None) - created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + repo_field_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) + field_key = Column(String(250, convert_unicode=False)) + field_label = Column(String(1024, convert_unicode=False), nullable=False) + field_value = Column(String(10000, convert_unicode=False), nullable=False) + field_desc = Column(String(1024, convert_unicode=False), nullable=False) + field_type = Column(String(255), nullable=False, unique=None) + created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) repository = relationship('Repository') @@ -944,26 +944,26 @@ 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) + repo_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + repo_name = Column(String(255, convert_unicode=False), nullable=False, unique=True, default=None) + repo_state = Column(String(255), nullable=True) + + clone_uri = Column(String(255, convert_unicode=False), nullable=True, unique=False, default=None) + repo_type = Column(String(255, convert_unicode=False), nullable=False, unique=False, default=None) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + private = Column(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) + description = Column(String(10000, convert_unicode=False), nullable=True, unique=None, default=None) + created_on = Column(DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) + updated_on = Column(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) + enable_locking = Column(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) + fork_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) + group_id = Column(Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) user = relationship('User') fork = relationship('Repository', remote_side=repo_id) @@ -1277,7 +1277,7 @@ pass return get_clone_url(uri_tmpl=uri_tmpl, - qualifed_home_url=qualified_home_url, + qualified_home_url=qualified_home_url, repo_name=self.repo_name, repo_id=self.repo_id, **override) @@ -1384,12 +1384,13 @@ grouped = {} for stat in statuses.all(): - pr_id = pr_repo = None + pr_id = pr_nice_id = pr_repo = None if stat.pull_request: pr_id = stat.pull_request.pull_request_id + pr_nice_id = PullRequest.make_nice_id(pr_id) pr_repo = stat.pull_request.other_repo.repo_name grouped[stat.revision] = [str(stat.status), stat.status_lbl, - pr_id, pr_repo] + pr_id, pr_repo, pr_nice_id] return grouped def _repo_size(self): @@ -1463,13 +1464,13 @@ 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) + group_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + group_name = Column(String(255, convert_unicode=False), nullable=False, unique=True, default=None) + group_parent_id = Column(Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) + group_description = Column(String(10000, convert_unicode=False), nullable=True, unique=None, default=None) + enable_locking = Column(Boolean(), nullable=False, unique=None, default=False) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) + created_on = Column(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') @@ -1728,9 +1729,9 @@ '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) + permission_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + permission_name = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) + permission_longname = Column(String(255, convert_unicode=False), nullable=True, unique=None, default=None) def __unicode__(self): return u"<%s('%s:%s')>" % ( @@ -1776,10 +1777,10 @@ {'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) + repo_to_perm_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column(Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) user = relationship('User') repository = relationship('Repository') @@ -1805,10 +1806,10 @@ {'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_user_group_to_perm_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column(Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column(Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) user = relationship('User') user_group = relationship('UserGroup') @@ -1834,9 +1835,9 @@ {'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_to_perm_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + permission_id = Column(Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) user = relationship('User') permission = relationship('Permission') @@ -1852,10 +1853,10 @@ {'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_to_perm_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column(Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column(Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + repository_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) users_group = relationship('UserGroup') permission = relationship('Permission') @@ -1882,10 +1883,10 @@ {'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) + user_group_user_group_to_perm_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + target_user_group_id = Column(Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column(Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + user_group_id = Column(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') @@ -1911,9 +1912,9 @@ {'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_to_perm_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column(Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column(Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) users_group = relationship('UserGroup') permission = relationship('Permission') @@ -1927,10 +1928,10 @@ '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) + group_to_perm_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) + group_id = Column(Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column(Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) user = relationship('User') group = relationship('RepoGroup') @@ -1954,10 +1955,10 @@ '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_repo_group_to_perm_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column(Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + group_id = Column(Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) + permission_id = Column(Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) users_group = relationship('UserGroup') permission = relationship('Permission') @@ -1980,12 +1981,12 @@ {'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 + stat_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + repository_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) + stat_on_revision = Column(Integer(), nullable=False) + commit_activity = Column(LargeBinary(1000000), nullable=False)#JSON data + commit_activity_combined = Column(LargeBinary(), nullable=False)#JSON data + languages = Column(LargeBinary(1000000), nullable=False)#JSON data repository = relationship('Repository', single_parent=True) @@ -1999,11 +2000,11 @@ '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) + user_following_id = Column(Integer(), nullable=False, unique=True, default=None, primary_key=True) + user_id = Column(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) + follows_user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + follows_from = Column(DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') @@ -2024,14 +2025,14 @@ '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_id = Column(Integer(), nullable=False, unique=True, 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_key = Column(String(255, convert_unicode=False)) # 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) + cache_args = Column(String(255, convert_unicode=False)) + # 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(Boolean(), nullable=True, unique=None, default=False) def __init__(self, cache_key, repo_name=''): self.cache_key = cache_key @@ -2039,8 +2040,9 @@ 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) + 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) @@ -2143,24 +2145,25 @@ {'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) + comment_id = Column(Integer(), nullable=False, primary_key=True) + repo_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False) + revision = Column(String(40)) + pull_request_id = Column(Integer(), ForeignKey('pull_requests.pull_request_id')) + line_no = Column(Unicode(10)) + hl_lines = Column(Unicode(512)) + f_path = Column(Unicode(1000)) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False) + text = Column(UnicodeText(25000), nullable=False) + created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) author = relationship('User') repo = relationship('Repository') # status_change is frequently used directly in templates - make it a lazy # join to avoid fetching each related ChangesetStatus on demand. # There will only be one ChangesetStatus referencing each comment so the join will not explode. - status_change = relationship('ChangesetStatus', cascade="all, delete-orphan", lazy='joined') + status_change = relationship('ChangesetStatus', + cascade="all, delete-orphan", lazy='joined') pull_request = relationship('PullRequest') @classmethod @@ -2205,15 +2208,15 @@ (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) + changeset_status_id = Column(Integer(), nullable=False, primary_key=True) + repo_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) + revision = Column(String(40), nullable=False) + status = Column(String(128), nullable=False, default=DEFAULT) + changeset_comment_id = Column(Integer(), ForeignKey('changeset_comments.comment_id')) + modified_at = Column(DateTime(), nullable=False, default=datetime.datetime.now) + version = Column(Integer(), nullable=False, default=0) + pull_request_id = Column(Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) author = relationship('User') repo = relationship('Repository') @@ -2248,18 +2251,18 @@ STATUS_NEW = u'new' STATUS_CLOSED = u'closed' - pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) - title = Column('title', Unicode(255), nullable=True) - description = Column('description', UnicodeText(10240), nullable=True) - status = Column('status', Unicode(255), 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) + pull_request_id = Column(Integer(), primary_key=True) + title = Column(Unicode(255), nullable=True) + description = Column(UnicodeText(10240)) + status = Column(Unicode(255), nullable=False, default=STATUS_NEW) # only for closedness, not approve/reject/etc + created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + updated_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + user_id = Column(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(255), nullable=False) - other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) - other_ref = Column('other_ref', Unicode(255), nullable=False) + org_repo_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False) + org_ref = Column(Unicode(255), nullable=False) + other_repo_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False) + other_ref = Column(Unicode(255), nullable=False) @hybrid_property def revisions(self): @@ -2303,6 +2306,15 @@ .first() return str(status.status) if status else '' + @classmethod + def make_nice_id(cls, pull_request_id): + '''Return pull request id nicely formatted for displaying''' + return '#%s' % pull_request_id + + def nice_id(self): + '''Return the id of this pull request, nicely formatted for displaying''' + return self.make_nice_id(self.pull_request_id) + def __json__(self): return dict( revisions=self.revisions @@ -2334,9 +2346,9 @@ 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) + pull_requests_reviewers_id = Column(Integer(), nullable=False, primary_key=True) + pull_request_id = Column(Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False) + user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=True) user = relationship('User') pull_request = relationship('PullRequest') @@ -2357,11 +2369,11 @@ 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) + notification_id = Column(Integer(), nullable=False, primary_key=True) + subject = Column(Unicode(512), nullable=True) + body = Column(UnicodeText(50000), nullable=True) + created_by = Column(Integer(), ForeignKey('users.user_id'), nullable=True) + created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) type_ = Column('type', Unicode(255)) created_by_user = relationship('User') @@ -2369,8 +2381,8 @@ @property def recipients(self): - return [x.user for x in UserNotification.query()\ - .filter(UserNotification.notification == self)\ + return [x.user for x in UserNotification.query() + .filter(UserNotification.notification == self) .order_by(UserNotification.user_id.asc()).all()] @classmethod @@ -2407,10 +2419,10 @@ {'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_id = Column(Integer(), ForeignKey('users.user_id'), primary_key=True) + notification_id = Column(Integer(), ForeignKey('notifications.notification_id'), primary_key=True) + read = Column(Boolean, default=False) + sent_on = Column(DateTime(timezone=False), nullable=True, unique=None) user = relationship('User') notification = relationship('Notification') @@ -2432,14 +2444,14 @@ 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_id = Column(Integer(), primary_key=True) + gist_access_id = Column(Unicode(250)) + gist_description = Column(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) + gist_expires = Column(Float(53), nullable=False) + gist_type = Column(Unicode(128), nullable=False) + created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + modified_at = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now) owner = relationship('User') @@ -2516,6 +2528,6 @@ {'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) + repository_id = Column(String(250), primary_key=True) + repository_path = Column(Text) + version = Column(Integer) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/model/notification.py --- a/kallithea/model/notification.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/model/notification.py Thu May 07 16:24:29 2015 +0200 @@ -298,8 +298,8 @@ # self.TYPE_PASSWORD_RESET self.TYPE_REGISTRATION: _('New user %(new_username)s registered'), # self.TYPE_DEFAULT - self.TYPE_PULL_REQUEST: _('Review request on %(repo_name)s pull request #%(pr_id)s from %(ref)s by %(pr_username)s'), - self.TYPE_PULL_REQUEST_COMMENT: _('Comment on %(repo_name)s pull request #%(pr_id)s from %(ref)s by %(comment_username)s'), + self.TYPE_PULL_REQUEST: _('Review request on %(repo_name)s pull request %(pr_nice_id)s from %(ref)s by %(pr_username)s'), + self.TYPE_PULL_REQUEST_COMMENT: _('Comment on %(repo_name)s pull request %(pr_nice_id)s from %(ref)s by %(comment_username)s'), } def get_email_description(self, type_, **kwargs): diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/model/pull_request.py --- a/kallithea/model/pull_request.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/model/pull_request.py Thu May 07 16:24:29 2015 +0200 @@ -130,10 +130,10 @@ h.canonical_hostname())] subject = safe_unicode( h.link_to( - _('%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s') % \ + _('%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s') % \ {'user': pr.author.username, 'pr_title': pr.title, - 'pr_id': pr.pull_request_id}, + 'pr_nice_id': pr.nice_id()}, pr_url) ) body = pr.description @@ -145,7 +145,7 @@ 'pr_url': pr_url, 'pr_revisions': revision_data, 'repo_name': pr.other_repo.repo_name, - 'pr_id': pr.pull_request_id, + 'pr_nice_id': pr.nice_id(), 'ref': org_ref_name, 'pr_username': pr.author.username, 'threading': threading, diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/model/user.py --- a/kallithea/model/user.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/model/user.py Thu May 07 16:24:29 2015 +0200 @@ -81,12 +81,17 @@ if not cur_user: cur_user = getattr(get_current_authuser(), 'username', None) - from kallithea.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'], - 'email': _fd['email'], 'firstname': _fd['firstname'], 'lastname': _fd['lastname'], - 'active': _fd['active'], 'admin': False + 'username': _fd['username'], + 'password': _fd['password'], + 'email': _fd['email'], + 'firstname': _fd['firstname'], + 'lastname': _fd['lastname'], + 'active': _fd['active'], + 'admin': False } # raises UserCreationError if it's not allowed check_allowed_create_user(user_data, cur_user) @@ -128,7 +133,8 @@ cur_user = getattr(get_current_authuser(), 'username', None) from kallithea.lib.auth import get_crypt_password, check_password - from kallithea.lib.hooks import log_create_user, check_allowed_create_user + from kallithea.lib.hooks import log_create_user, \ + check_allowed_create_user user_data = { 'username': username, 'password': password, 'email': email, 'firstname': firstname, 'lastname': lastname, @@ -153,8 +159,10 @@ new_user.admin = admin new_user.email = email new_user.active = active - 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.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 @@ -162,12 +170,13 @@ 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) + 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 + new_user.password = get_crypt_password(password) \ + if password else None self.sa.add(new_user) @@ -192,14 +201,17 @@ # notification to admins subject = _('New user registration') - body = ('New user registration\n' - '---------------------\n' - '- Username: %s\n' - '- Full Name: %s\n' - '- Email: %s\n') - body = body % (new_user.username, new_user.full_name, new_user.email) + body = ( + 'New user registration\n' + '---------------------\n' + '- Username: {user.username}\n' + '- Full Name: {user.full_name}\n' + '- Email: {user.email}\n' + ).format(user=new_user) edit_url = h.canonical_url('edit_user', id=new_user.user_id) - email_kwargs = {'registered_user_url': edit_url, 'new_username': new_user.username} + email_kwargs = { + 'registered_user_url': edit_url, + 'new_username': new_user.username} NotificationModel().create(created_by=new_user, subject=subject, body=body, recipients=None, type_=Notification.TYPE_REGISTRATION, @@ -253,29 +265,25 @@ if user.username == User.DEFAULT_USER: raise DefaultUserException( _(u"You can't remove this user since it's" - " crucial for entire application") - ) + " crucial for entire application")) if user.repositories: repos = [x.repo_name for x in user.repositories] raise UserOwnsReposException( _(u'User "%s" still owns %s repositories and cannot be ' 'removed. Switch owners or remove those repositories: %s') - % (user.username, len(repos), ', '.join(repos)) - ) + % (user.username, len(repos), ', '.join(repos))) if user.repo_groups: repogroups = [x.group_name for x in user.repo_groups] - raise UserOwnsReposException( - _(u'User "%s" still owns %s repository groups and cannot be ' - 'removed. Switch owners or remove those repository groups: %s') - % (user.username, len(repogroups), ', '.join(repogroups)) - ) + raise UserOwnsReposException(_( + 'User "%s" still owns %s repository groups and cannot be ' + 'removed. Switch owners or remove those repository groups: %s') + % (user.username, len(repogroups), ', '.join(repogroups))) if user.user_groups: usergroups = [x.users_group_name for x in user.user_groups] raise UserOwnsReposException( - _(u'User "%s" still owns %s user groups and cannot be ' + _('User "%s" still owns %s user groups and cannot be ' 'removed. Switch owners or remove those user groups: %s') - % (user.username, len(usergroups), ', '.join(usergroups)) - ) + % (user.username, len(usergroups), ', '.join(usergroups))) self.sa.delete(user) from kallithea.lib.hooks import log_delete_user @@ -290,16 +298,17 @@ user = User.get_by_email(user_email) if user: log.debug('password reset user found %s' % user) - link = h.canonical_url('reset_password_confirmation', key=user.api_key) + link = h.canonical_url('reset_password_confirmation', + key=user.api_key) reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET - body = EmailNotificationModel().get_email_tmpl(reg_type, - 'txt', - user=user.short_contact, - reset_url=link) - html_body = EmailNotificationModel().get_email_tmpl(reg_type, - 'html', - user=user.short_contact, - reset_url=link) + body = EmailNotificationModel().get_email_tmpl( + reg_type, 'txt', + user=user.short_contact, + reset_url=link) + html_body = EmailNotificationModel().get_email_tmpl( + reg_type, 'html', + user=user.short_contact, + reset_url=link) log.debug('sending email') run_task(tasks.send_email, [user_email], _("Password reset link"), body, html_body) @@ -314,8 +323,8 @@ from kallithea.lib import auth user_email = data['email'] user = User.get_by_email(user_email) - new_passwd = auth.PasswordGenerator().gen_password(8, - auth.PasswordGenerator.ALPHABETS_BIG_SMALL) + new_passwd = auth.PasswordGenerator().gen_password( + 8, auth.PasswordGenerator.ALPHABETS_BIG_SMALL) if user: user.password = auth.get_crypt_password(new_passwd) Session().add(user) @@ -401,12 +410,10 @@ user = self._get_user(user) perm = self._get_perm(perm) - obj = UserToPerm.query()\ - .filter(UserToPerm.user == user)\ - .filter(UserToPerm.permission == perm)\ - .scalar() - if obj: - self.sa.delete(obj) + UserToPerm.query().filter( + UserToPerm.user == user, + UserToPerm.permission == perm, + ).delete() def add_extra_email(self, user, email): """ diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/public/css/contextbar.css --- a/kallithea/public/css/contextbar.css Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/public/css/contextbar.css Thu May 07 16:24:29 2015 +0200 @@ -19,19 +19,19 @@ .icon-diff-M:before { font-family: 'kallithea'; - content: '\e805'; + content: '\22a1'; color: #d0b44c; } .icon-diff-D:before { font-family: 'kallithea'; - content: '\e807'; + content: '\229f'; color: #bd2c00; } .icon-diff-A:before { font-family: 'kallithea'; - content: '\e806'; + content: '\229e'; color: #6cc644; } @@ -279,7 +279,8 @@ #revision-changer:before, #context-pages a.childs:after, #context-pages a.dropdown:after { - content: ' \25BE'; + font-family: 'kallithea'; + content: ' \23f7'; } #context-pages a.childs { padding-right: 30px; diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/public/css/style.css --- a/kallithea/public/css/style.css Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/public/css/style.css Thu May 07 16:24:29 2015 +0200 @@ -510,7 +510,7 @@ td.quick_repo_menu:before { font-family: "kallithea"; - content: "\e80f"; /* triangle-right */ + content: "\23f5"; /* triangle-right */ margin-left: 3px; padding-right: 3px; } @@ -523,7 +523,7 @@ td.quick_repo_menu.active:before { font-family: "kallithea"; - content: "\e80d"; /* triangle-down */ + content: "\23f7"; /* triangle-down */ margin-left: 1px; padding-right: 1px; } @@ -735,12 +735,12 @@ .yui-skin-sam th.yui-dt-asc .yui-dt-liner:after { font-family: "kallithea"; - content: "\e810"; /* triangle-up */ + content: "\23f6"; /* triangle-up */ } .yui-skin-sam th.yui-dt-desc .yui-dt-liner:after { font-family: "kallithea"; - content: "\e80d"; /* triangle-down */ + content: "\23f7"; /* triangle-down */ } tbody .yui-dt-editable { cursor: pointer } @@ -3715,7 +3715,8 @@ } .repo-switcher .select2-chosen:after { - content: ' \25BE'; + font-family: 'kallithea'; + content: ' \23f7'; } .repo-switcher-dropdown.select2-drop.select2-drop-active { @@ -4346,6 +4347,10 @@ font-size: 16px; } +.automatic-comment { + font-style: italic; +} + /** comment form **/ .status-block { @@ -4968,7 +4973,7 @@ position: relative; width: 0; } - + table.code-difftable .add .code pre:before { content: "+"; color: #080; @@ -4977,7 +4982,7 @@ position: relative; width: 0; } - + table.code-difftable .unmod .code pre:before { content: " "; float: left; @@ -4985,7 +4990,7 @@ position: relative; width: 0; } - + .add-bubble { position: relative; display: none; @@ -5022,7 +5027,7 @@ font-size: 14px; color: #ffffff; font-family: "kallithea"; - content: '\e80c'; + content: '\1f5ea'; } .add-bubble div:hover { diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/public/fontello/config.json --- a/kallithea/public/fontello/config.json Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/public/fontello/config.json Thu May 07 16:24:29 2015 +0200 @@ -401,7 +401,7 @@ { "uid": "c04672812513206682a859166c207252", "css": "clippy", - "code": 59419, + "code": 128203, "src": "custom_icons", "selected": true, "svg": { @@ -457,7 +457,7 @@ { "uid": "c9e14800494dc6027b3dcee0817cf984", "css": "code", - "code": 59425, + "code": 8596, "src": "custom_icons", "selected": true, "svg": { @@ -485,7 +485,7 @@ { "uid": "7aeda197b5b0fba630669530807d736d", "css": "comment", - "code": 59403, + "code": 128489, "src": "custom_icons", "selected": true, "svg": { @@ -499,7 +499,7 @@ { "uid": "28655242f029e97efd1bf5379e22c4ba", "css": "comment-discussion", - "code": 59404, + "code": 128490, "src": "custom_icons", "selected": true, "svg": { @@ -555,7 +555,7 @@ { "uid": "776af96a4db73c51c13fd256f12d6f40", "css": "database", - "code": 59392, + "code": 9923, "src": "custom_icons", "selected": true, "svg": { @@ -639,7 +639,7 @@ { "uid": "ccc8f787411138446b85c9fe52e33b8b", "css": "diff-added", - "code": 59398, + "code": 8862, "src": "custom_icons", "selected": true, "svg": { @@ -667,7 +667,7 @@ { "uid": "2672a84540d3632649f01108e2db0341", "css": "diff-modified", - "code": 59397, + "code": 8865, "src": "custom_icons", "selected": true, "svg": { @@ -681,7 +681,7 @@ { "uid": "1ce39df7ee1648c4054633b371546367", "css": "diff-removed", - "code": 59399, + "code": 8863, "src": "custom_icons", "selected": true, "svg": { @@ -905,7 +905,7 @@ { "uid": "c59600c892bd7e46476f38e89812fbbf", "css": "gear", - "code": 59441, + "code": 9965, "src": "custom_icons", "selected": true, "svg": { @@ -1031,7 +1031,7 @@ { "uid": "b00e349d8883c0b89796940a9913e8e8", "css": "globe", - "code": 59410, + "code": 127758, "src": "custom_icons", "selected": true, "svg": { @@ -1283,7 +1283,7 @@ { "uid": "3617d121a15ef91892d5083aeead6ce3", "css": "key", - "code": 59430, + "code": 128273, "src": "custom_icons", "selected": true, "svg": { @@ -1591,7 +1591,7 @@ { "uid": "ef6263a57a35ecee2f8ddda2fe20dcab", "css": "move-down", - "code": 59395, + "code": 11123, "src": "custom_icons", "selected": true, "svg": { @@ -1633,7 +1633,7 @@ { "uid": "13e7ebf511552da48a5bc1d2e7cf6de2", "css": "move-up", - "code": 59396, + "code": 11121, "src": "custom_icons", "selected": true, "svg": { @@ -2123,7 +2123,7 @@ { "uid": "809bb7ea7bf6ca7e94029eae402f922f", "css": "search", - "code": 59435, + "code": 128269, "src": "custom_icons", "selected": true, "svg": { @@ -2333,7 +2333,7 @@ { "uid": "92dd16866a2367537f47bec5ee11484f", "css": "tools", - "code": 59400, + "code": 128736, "src": "custom_icons", "selected": true, "svg": { @@ -2347,7 +2347,7 @@ { "uid": "448bfec39235117b6a7e3e8d46aa184f", "css": "trashcan", - "code": 59433, + "code": 128465, "src": "custom_icons", "selected": true, "svg": { @@ -2361,7 +2361,7 @@ { "uid": "ebbb1978bedc8e562ab0d462a832919f", "css": "triangle-down", - "code": 59405, + "code": 9207, "src": "custom_icons", "selected": true, "svg": { @@ -2375,7 +2375,7 @@ { "uid": "814cb1fe473de29d20b3d4e366ed434b", "css": "triangle-left", - "code": 59406, + "code": 9204, "src": "custom_icons", "selected": true, "svg": { @@ -2389,7 +2389,7 @@ { "uid": "d191392505c6a27bbeafd2d283a18d23", "css": "triangle-right", - "code": 59407, + "code": 9205, "src": "custom_icons", "selected": true, "svg": { @@ -2403,7 +2403,7 @@ { "uid": "14bdc9ddaebbaecf5bad552a14cae637", "css": "triangle-up", - "code": 59408, + "code": 9206, "src": "custom_icons", "selected": true, "svg": { @@ -2501,7 +2501,7 @@ { "uid": "16b70cc2a5fbff7de2cbf73498e25b5c", "css": "keyhole-circled", - "code": 59426, + "code": 128272, "src": "custom_icons", "selected": true, "svg": { @@ -2543,91 +2543,91 @@ { "uid": "d73eceadda1f594cec0536087539afbf", "css": "heart", - "code": 59436, + "code": 9829, "src": "fontawesome" }, { "uid": "f3dc2d6d8fe9cf9ebff84dc260888cdf", "css": "heart-empty", - "code": 59437, + "code": 9825, "src": "fontawesome" }, { "uid": "8b80d36d4ef43889db10bc1f0dc9a862", "css": "user", - "code": 59438, + "code": 128100, "src": "fontawesome" }, { "uid": "31972e4e9d080eaa796290349ae6c1fd", "css": "users", - "code": 59439, + "code": 128101, "src": "fontawesome" }, { "uid": "12f4ece88e46abd864e40b35e05b11cd", "css": "ok", - "code": 59440, + "code": 128504, "src": "fontawesome" }, { "uid": "43ab845088317bd348dee1d975700c48", "css": "ok-circled", - "code": 59402, + "code": 128505, "src": "fontawesome" }, { "uid": "5211af474d3a9848f67f945e2ccaf143", "css": "cancel", - "code": 59434, + "code": 128500, "src": "fontawesome" }, { "uid": "0f4cae16f34ae243a6144c18a003f2d8", "css": "cancel-circled", - "code": 59401, + "code": 128501, "src": "fontawesome" }, { "uid": "44e04715aecbca7f266a17d5a7863c68", "css": "plus", - "code": 59471, + "code": 10133, "src": "fontawesome" }, { "uid": "4ba33d2607902cf690dd45df09774cb0", "css": "plus-circled", - "code": 59468, + "code": 8853, "src": "fontawesome" }, { "uid": "861ab06e455e2de3232ebef67d60d708", "css": "minus", - "code": 59472, + "code": 10134, "src": "fontawesome" }, { "uid": "eeadb020bb75d089b25d8424aabe19e0", "css": "minus-circled", - "code": 59469, + "code": 8854, "src": "fontawesome" }, { "uid": "c1f1975c885aa9f3dad7810c53b82074", "css": "lock", - "code": 59450, + "code": 128274, "src": "fontawesome" }, { "uid": "05376be04a27d5a46e855a233d6e8508", "css": "lock-open-alt", - "code": 59451, + "code": 128275, "src": "fontawesome" }, { "uid": "c5fd349cbd3d23e4ade333789c29c729", "css": "eye", - "code": 59474, + "code": 128065, "src": "fontawesome" }, { @@ -2639,7 +2639,7 @@ { "uid": "3db5347bd219f3bce6025780f5d9ef45", "css": "tag", - "code": 59452, + "code": 128278, "src": "fontawesome" }, { @@ -2675,25 +2675,25 @@ { "uid": "d35a1d35efeb784d1dc9ac18b9b6c2b6", "css": "pencil", - "code": 59458, + "code": 128393, "src": "fontawesome" }, { "uid": "44fae3bfdd54754dc68ec50d37efea37", "css": "pencil-squared", - "code": 59460, + "code": 128394, "src": "fontawesome" }, { "uid": "41087bc74d4b20b55059c60a33bf4008", "css": "edit", - "code": 59461, + "code": 128395, "src": "fontawesome" }, { "uid": "1b5a5d7b7e3c71437f5a26befdd045ed", "css": "doc", - "code": 59443, + "code": 128453, "src": "fontawesome" }, { @@ -2705,7 +2705,7 @@ { "uid": "5408be43f7c42bccee419c6be53fdef5", "css": "doc-text", - "code": 59445, + "code": 128456, "src": "fontawesome" }, { @@ -2729,25 +2729,25 @@ { "uid": "f8aa663c489bcbd6e68ec8147dca841e", "css": "folder", - "code": 59475, + "code": 128448, "src": "fontawesome" }, { "uid": "c95735c17a10af81448c7fed98a04546", "css": "folder-open", - "code": 59462, + "code": 128449, "src": "fontawesome" }, { "uid": "b091a8bd0fdade174951f17d936f51e4", "css": "folder-empty", - "code": 59476, + "code": 128193, "src": "fontawesome" }, { "uid": "6533bdc16ab201eb3f3b27ce989cab33", "css": "folder-open-empty", - "code": 59463, + "code": 128194, "src": "fontawesome" }, { @@ -2771,13 +2771,13 @@ { "uid": "98687378abd1faf8f6af97c254eb6cd6", "css": "cog-alt", - "code": 59442, + "code": 9881, "src": "fontawesome" }, { "uid": "5bb103cd29de77e0e06a52638527b575", "css": "wrench", - "code": 59479, + "code": 128295, "src": "fontawesome" }, { @@ -2789,19 +2789,19 @@ { "uid": "598a5f2bcf3521d1615de8e1881ccd17", "css": "clock", - "code": 59449, + "code": 8986, "src": "fontawesome" }, { "uid": "98d9c83c1ee7c2c25af784b518c522c5", "css": "block", - "code": 59470, + "code": 128683, "src": "fontawesome" }, { "uid": "d3b3f17bc3eb7cd809a07bbd4d178bee", "css": "resize-vertical", - "code": 59415, + "code": 11109, "src": "fontawesome" }, { @@ -2825,25 +2825,25 @@ { "uid": "ccddff8e8670dcd130e3cb55fdfc2fd0", "css": "down-open", - "code": 59464, + "code": 8595, "src": "fontawesome" }, { "uid": "d870630ff8f81e6de3958ecaeac532f2", "css": "left-open", - "code": 59465, + "code": 8594, "src": "fontawesome" }, { "uid": "399ef63b1e23ab1b761dfbb5591fa4da", "css": "right-open", - "code": 59466, + "code": 8592, "src": "fontawesome" }, { "uid": "fe6697b391355dec12f3d86d6d490397", "css": "up-open", - "code": 59467, + "code": 8593, "src": "fontawesome" }, { @@ -2879,13 +2879,13 @@ { "uid": "a73c5deb486c8d66249811642e5d719a", "css": "arrows-cw", - "code": 59448, + "code": 128472, "src": "fontawesome" }, { "uid": "6020aff067fc3c119cdd75daa5249220", "css": "exchange", - "code": 59483, + "code": 8644, "src": "fontawesome" }, { @@ -2909,25 +2909,25 @@ { "uid": "9755f76110ae4d12ac5f9466c9152031", "css": "book", - "code": 59454, + "code": 128210, "src": "fontawesome" }, { "uid": "130380e481a7defc690dfb24123a1f0c", "css": "circle", - "code": 59485, + "code": 8226, "src": "fontawesome" }, { "uid": "422e07e5afb80258a9c4ed1706498f8a", "css": "circle-empty", - "code": 59484, + "code": 9702, "src": "fontawesome" }, { "uid": "f4445feb55521283572ee88bc304f928", "css": "floppy", - "code": 59480, + "code": 128190, "src": "fontawesome" }, { @@ -2939,7 +2939,7 @@ { "uid": "56a21935a5d4d79b2e91ec00f760b369", "css": "sort", - "code": 59482, + "code": 8597, "src": "fontawesome" } ] diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/public/fontello/css/kallithea.css --- a/kallithea/public/fontello/css/kallithea.css Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/public/fontello/css/kallithea.css Thu May 07 16:24:29 2015 +0200 @@ -1,10 +1,12 @@ -@font-face { +@charset "UTF-8"; + + @font-face { font-family: 'kallithea'; - src: url('../font/kallithea.eot?81834162'); - src: url('../font/kallithea.eot?81834162#iefix') format('embedded-opentype'), - url('../font/kallithea.woff?81834162') format('woff'), - url('../font/kallithea.ttf?81834162') format('truetype'), - url('../font/kallithea.svg?81834162#kallithea') format('svg'); + src: url('../font/kallithea.eot?23730278'); + src: url('../font/kallithea.eot?23730278#iefix') format('embedded-opentype'), + url('../font/kallithea.woff?23730278') format('woff'), + url('../font/kallithea.ttf?23730278') format('truetype'), + url('../font/kallithea.svg?23730278#kallithea') format('svg'); font-weight: normal; font-style: normal; } @@ -14,7 +16,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'kallithea'; - src: url('../font/kallithea.svg?81834162#kallithea') format('svg'); + src: url('../font/kallithea.svg?23730278#kallithea') format('svg'); } } */ @@ -35,7 +37,7 @@ /* For safety - reset parent styles, that can break glyph codes*/ font-variant: normal; text-transform: none; - + /* fix buttons height, for twitter bootstrap */ line-height: 1em; @@ -46,102 +48,73 @@ /* you can be more comfortable with increased icons size */ /* font-size: 120%; */ + /* Font smoothing. That was taken from TWBS */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + /* Uncomment for 3D effect */ /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ } -.icon-database:before { content: '\e800'; } /* '' */ +.icon-circle:before { content: '\2022'; } /* '•' */ +.icon-right-open:before { content: '\2190'; } /* '←' */ +.icon-up-open:before { content: '\2191'; } /* '↑' */ +.icon-left-open:before { content: '\2192'; } /* '→' */ +.icon-down-open:before { content: '\2193'; } /* '↓' */ +.icon-code:before { content: '\2194'; } /* '↔' */ +.icon-sort:before { content: '\2195'; } /* '↕' */ +.icon-exchange:before { content: '\21c4'; } /* '⇄' */ +.icon-plus-circled:before { content: '\2295'; } /* '⊕' */ +.icon-minus-circled:before { content: '\2296'; } /* '⊖' */ +.icon-diff-added:before { content: '\229e'; } /* '⊞' */ +.icon-diff-removed:before { content: '\229f'; } /* '⊟' */ +.icon-diff-modified:before { content: '\22a1'; } /* '⊡' */ +.icon-clock:before { content: '\231a'; } /* '⌚' */ +.icon-triangle-left:before { content: '\23f4'; } /* '⏴' */ +.icon-triangle-right:before { content: '\23f5'; } /* '⏵' */ +.icon-triangle-up:before { content: '\23f6'; } /* '⏶' */ +.icon-triangle-down:before { content: '\23f7'; } /* '⏷' */ +.icon-circle-empty:before { content: '\25e6'; } /* '◦' */ +.icon-heart-empty:before { content: '\2661'; } /* '♡' */ +.icon-heart:before { content: '\2665'; } /* '♥' */ +.icon-cog-alt:before { content: '\2699'; } /* '⚙' */ +.icon-database:before { content: '\26c3'; } /* '⛃' */ +.icon-gear:before { content: '\26ed'; } /* '⛭' */ +.icon-plus:before { content: '\2795'; } /* '➕' */ +.icon-minus:before { content: '\2796'; } /* '➖' */ +.icon-resize-vertical:before { content: '\2b65'; } /* '⭥' */ +.icon-move-up:before { content: '\2b71'; } /* '⭱' */ +.icon-move-down:before { content: '\2b73'; } /* '⭳' */ .icon-file-submodule:before { content: '\e801'; } /* '' */ .icon-git-merge:before { content: '\e802'; } /* '' */ -.icon-move-down:before { content: '\e803'; } /* '' */ -.icon-move-up:before { content: '\e804'; } /* '' */ -.icon-diff-modified:before { content: '\e805'; } /* '' */ -.icon-diff-added:before { content: '\e806'; } /* '' */ -.icon-diff-removed:before { content: '\e807'; } /* '' */ -.icon-tools:before { content: '\e808'; } /* '' */ -.icon-cancel-circled:before { content: '\e809'; } /* '' */ -.icon-ok-circled:before { content: '\e80a'; } /* '' */ -.icon-comment:before { content: '\e80b'; } /* '' */ -.icon-comment-discussion:before { content: '\e80c'; } /* '' */ -.icon-triangle-down:before { content: '\e80d'; } /* '' */ -.icon-triangle-left:before { content: '\e80e'; } /* '' */ -.icon-triangle-right:before { content: '\e80f'; } /* '' */ -.icon-triangle-up:before { content: '\e810'; } /* '' */ .icon-ruler:before { content: '\e811'; } /* '' */ -.icon-globe:before { content: '\e812'; } /* '' */ .icon-download-cloud:before { content: '\e813'; } /* '' */ .icon-upload-cloud:before { content: '\e814'; } /* '' */ .icon-graph:before { content: '\e815'; } /* '' */ .icon-file-zip:before { content: '\e816'; } /* '' */ -.icon-resize-vertical:before { content: '\e817'; } /* '' */ .icon-file-code:before { content: '\e81a'; } /* '' */ -.icon-clippy:before { content: '\e81b'; } /* '' */ .icon-doc-text-inv:before { content: '\e81c'; } /* '' */ .icon-diff:before { content: '\e81d'; } /* '' */ .icon-diff-ignored:before { content: '\e81e'; } /* '' */ .icon-diff-renamed:before { content: '\e81f'; } /* '' */ .icon-paste:before { content: '\e820'; } /* '' */ -.icon-code:before { content: '\e821'; } /* '' */ -.icon-keyhole-circled:before { content: '\e822'; } /* '' */ .icon-file-directory:before { content: '\e823'; } /* '' */ .icon-git-compare:before { content: '\e824'; } /* '' */ .icon-git-pull-request:before { content: '\e825'; } /* '' */ -.icon-key:before { content: '\e826'; } /* '' */ .icon-repo-forked:before { content: '\e827'; } /* '' */ .icon-fork:before { content: '\e828'; } /* '' */ -.icon-trashcan:before { content: '\e829'; } /* '' */ -.icon-cancel:before { content: '\e82a'; } /* '' */ -.icon-search:before { content: '\e82b'; } /* '' */ -.icon-heart:before { content: '\e82c'; } /* '' */ -.icon-heart-empty:before { content: '\e82d'; } /* '' */ -.icon-user:before { content: '\e82e'; } /* '' */ -.icon-users:before { content: '\e82f'; } /* '' */ -.icon-ok:before { content: '\e830'; } /* '' */ -.icon-gear:before { content: '\e831'; } /* '' */ -.icon-cog-alt:before { content: '\e832'; } /* '' */ -.icon-doc:before { content: '\e833'; } /* '' */ .icon-docs:before { content: '\e834'; } /* '' */ -.icon-doc-text:before { content: '\e835'; } /* '' */ .icon-doc-inv:before { content: '\e836'; } /* '' */ .icon-file-powerpoint:before { content: '\e837'; } /* '' */ -.icon-arrows-cw:before { content: '\e838'; } /* '' */ -.icon-clock:before { content: '\e839'; } /* '' */ -.icon-lock:before { content: '\e83a'; } /* '' */ -.icon-lock-open-alt:before { content: '\e83b'; } /* '' */ -.icon-tag:before { content: '\e83c'; } /* '' */ .icon-tags:before { content: '\e83d'; } /* '' */ -.icon-book:before { content: '\e83e'; } /* '' */ .icon-bookmark-empty:before { content: '\e83f'; } /* '' */ .icon-bookmark:before { content: '\e840'; } /* '' */ .icon-align-left:before { content: '\e841'; } /* '' */ -.icon-pencil:before { content: '\e842'; } /* '' */ .icon-sliders:before { content: '\e843'; } /* '' */ -.icon-pencil-squared:before { content: '\e844'; } /* '' */ -.icon-edit:before { content: '\e845'; } /* '' */ -.icon-folder-open:before { content: '\e846'; } /* '' */ -.icon-folder-open-empty:before { content: '\e847'; } /* '' */ -.icon-down-open:before { content: '\e848'; } /* '' */ -.icon-left-open:before { content: '\e849'; } /* '' */ -.icon-right-open:before { content: '\e84a'; } /* '' */ -.icon-up-open:before { content: '\e84b'; } /* '' */ -.icon-plus-circled:before { content: '\e84c'; } /* '' */ -.icon-minus-circled:before { content: '\e84d'; } /* '' */ -.icon-block:before { content: '\e84e'; } /* '' */ -.icon-plus:before { content: '\e84f'; } /* '' */ -.icon-minus:before { content: '\e850'; } /* '' */ .icon-eye-off:before { content: '\e851'; } /* '' */ -.icon-eye:before { content: '\e852'; } /* '' */ -.icon-folder:before { content: '\e853'; } /* '' */ -.icon-folder-empty:before { content: '\e854'; } /* '' */ .icon-rss:before { content: '\e855'; } /* '' */ .icon-rss-squared:before { content: '\e856'; } /* '' */ -.icon-wrench:before { content: '\e857'; } /* '' */ -.icon-floppy:before { content: '\e858'; } /* '' */ .icon-strike:before { content: '\e859'; } /* '' */ -.icon-sort:before { content: '\e85a'; } /* '' */ -.icon-exchange:before { content: '\e85b'; } /* '' */ -.icon-circle-empty:before { content: '\e85c'; } /* '' */ -.icon-circle:before { content: '\e85d'; } /* '' */ .icon-box:before { content: '\e85e'; } /* '' */ .icon-right:before { content: '\e85f'; } /* '' */ .icon-left:before { content: '\e860'; } /* '' */ @@ -150,4 +123,37 @@ .icon-up-circled:before { content: '\e863'; } /* '' */ .icon-up:before { content: '\e864'; } /* '' */ .icon-down:before { content: '\e865'; } /* '' */ -.icon-down-circled:before { content: '\e866'; } /* '' */ \ No newline at end of file +.icon-down-circled:before { content: '\e866'; } /* '' */ +.icon-globe:before { content: '🌎'; } /* '\1f30e' */ +.icon-eye:before { content: '👁'; } /* '\1f441' */ +.icon-user:before { content: '👤'; } /* '\1f464' */ +.icon-users:before { content: '👥'; } /* '\1f465' */ +.icon-floppy:before { content: '💾'; } /* '\1f4be' */ +.icon-folder-empty:before { content: '📁'; } /* '\1f4c1' */ +.icon-folder-open-empty:before { content: '📂'; } /* '\1f4c2' */ +.icon-clippy:before { content: '📋'; } /* '\1f4cb' */ +.icon-book:before { content: '📒'; } /* '\1f4d2' */ +.icon-search:before { content: '🔍'; } /* '\1f50d' */ +.icon-keyhole-circled:before { content: '🔐'; } /* '\1f510' */ +.icon-key:before { content: '🔑'; } /* '\1f511' */ +.icon-lock:before { content: '🔒'; } /* '\1f512' */ +.icon-lock-open-alt:before { content: '🔓'; } /* '\1f513' */ +.icon-tag:before { content: '🔖'; } /* '\1f516' */ +.icon-wrench:before { content: '🔧'; } /* '\1f527' */ +.icon-pencil:before { content: '🖉'; } /* '\1f589' */ +.icon-pencil-squared:before { content: '🖊'; } /* '\1f58a' */ +.icon-edit:before { content: '🖋'; } /* '\1f58b' */ +.icon-folder:before { content: '🗀'; } /* '\1f5c0' */ +.icon-folder-open:before { content: '🗁'; } /* '\1f5c1' */ +.icon-doc:before { content: '🗅'; } /* '\1f5c5' */ +.icon-doc-text:before { content: '🗈'; } /* '\1f5c8' */ +.icon-trashcan:before { content: '🗑'; } /* '\1f5d1' */ +.icon-arrows-cw:before { content: '🗘'; } /* '\1f5d8' */ +.icon-comment:before { content: '🗩'; } /* '\1f5e9' */ +.icon-comment-discussion:before { content: '🗪'; } /* '\1f5ea' */ +.icon-cancel:before { content: '🗴'; } /* '\1f5f4' */ +.icon-cancel-circled:before { content: '🗵'; } /* '\1f5f5' */ +.icon-ok:before { content: '🗸'; } /* '\1f5f8' */ +.icon-ok-circled:before { content: '🗹'; } /* '\1f5f9' */ +.icon-block:before { content: '🚫'; } /* '\1f6ab' */ +.icon-tools:before { content: '🛠'; } /* '\1f6e0' */ \ No newline at end of file diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/public/fontello/font/kallithea.eot Binary file kallithea/public/fontello/font/kallithea.eot has changed diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/public/fontello/font/kallithea.svg --- a/kallithea/public/fontello/font/kallithea.svg Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/public/fontello/font/kallithea.svg Thu May 07 16:24:29 2015 +0200 @@ -6,98 +6,65 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -107,6 +74,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/public/fontello/font/kallithea.ttf Binary file kallithea/public/fontello/font/kallithea.ttf has changed diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/public/fontello/font/kallithea.woff Binary file kallithea/public/fontello/font/kallithea.woff has changed diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/admin/auth/auth_settings.html --- a/kallithea/templates/admin/auth/auth_settings.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/admin/auth/auth_settings.html Thu May 07 16:24:29 2015 +0200 @@ -58,7 +58,7 @@
- ${h.password(fullsetting,class_='small',autocomplete="off")} + ${h.password(fullsetting,class_='small')} ${setting["description"]}
diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/admin/my_account/my_account_password.html --- a/kallithea/templates/admin/my_account/my_account_password.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/admin/my_account/my_account_password.html Thu May 07 16:24:29 2015 +0200 @@ -7,7 +7,7 @@
- ${h.password('current_password',class_='medium',autocomplete="off")} + ${h.password('current_password',class_='medium')}
@@ -16,7 +16,7 @@
- ${h.password('new_password',class_='medium', autocomplete="off")} + ${h.password('new_password',class_='medium')}
@@ -25,7 +25,7 @@
- ${h.password('new_password_confirmation',class_='medium', autocomplete="off")} + ${h.password('new_password_confirmation',class_='medium')}
diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/admin/users/user_add.html --- a/kallithea/templates/admin/users/user_add.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/admin/users/user_add.html Thu May 07 16:24:29 2015 +0200 @@ -41,7 +41,7 @@
- ${h.password('password',class_='small',autocomplete="off")} + ${h.password('password',class_='small')}
@@ -50,7 +50,7 @@
- ${h.password('password_confirmation',class_="small",autocomplete="off")} + ${h.password('password_confirmation',class_="small")}
diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/admin/users/user_edit.html --- a/kallithea/templates/admin/users/user_edit.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/admin/users/user_edit.html Thu May 07 16:24:29 2015 +0200 @@ -29,7 +29,7 @@
  • ${_('Profile')}
  • ${_('API Keys')}
  • ${_('Advanced')}
  • -
  • ${_('Default Permissions')}
  • +
  • ${_('Permissions')}
  • ${_('Emails')}
  • ${_('IP Whitelist')}
  • diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/admin/users/user_edit_profile.html --- a/kallithea/templates/admin/users/user_edit_profile.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/admin/users/user_edit_profile.html Thu May 07 16:24:29 2015 +0200 @@ -69,7 +69,7 @@
    - ${h.password('new_password',class_='medium%s' % disabled,autocomplete="off",readonly=readonly)} + ${h.password('new_password',class_='medium%s' % disabled,readonly=readonly)}
    @@ -78,7 +78,7 @@
    - ${h.password('password_confirmation',class_="medium%s" % disabled,autocomplete="off",readonly=readonly)} + ${h.password('password_confirmation',class_="medium%s" % disabled,readonly=readonly)}
    diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/base/perms_summary.html --- a/kallithea/templates/base/perms_summary.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/base/perms_summary.html Thu May 07 16:24:29 2015 +0200 @@ -11,8 +11,8 @@ %if section != 'global':
    ${_('show')}: - ${h.checkbox('perms_filter_none_%s' % section, 'none', 'checked', class_='perm_filter filter_%s' % section, section=section, perm_type='none')} - ${h.checkbox('perms_filter_read_%s' % section, 'read', 'checked', class_='perm_filter filter_%s' % section, section=section, perm_type='read')} + ${h.checkbox('perms_filter_none_%s' % section, 'none', 'checked', class_='perm_filter filter_%s' % section, section=section, perm_type='none')} + ${h.checkbox('perms_filter_read_%s' % section, 'read', 'checked', class_='perm_filter filter_%s' % section, section=section, perm_type='read')} ${h.checkbox('perms_filter_write_%s' % section, 'write', 'checked', class_='perm_filter filter_%s' % section, section=section, perm_type='write')} ${h.checkbox('perms_filter_admin_%s' % section, 'admin', 'checked', class_='perm_filter filter_%s' % section, section=section, perm_type='admin')}
    @@ -108,15 +108,12 @@ $('#empty_{0}'.format(section)).hide(); } } - $('.perm_filter').on('change', function(e){ - var self = this; - var section = $(this).attr('section'); + var update_show = function($checkbox){ + var section = $checkbox.attr('section'); - var opts = {} var elems = $('.filter_' + section).each(function(el){ - var perm_type = $(this).attr('perm_type'); - var checked = this.checked; - opts[perm_type] = checked; + var perm_type = $checkbox.attr('perm_type'); + var checked = $checkbox.checked; if(checked){ $('.'+section+'_'+perm_type).show(); } @@ -125,8 +122,9 @@ } }); show_empty(section); - }) - + } + $('.perm_filter').on('change', function(){update_show($(this));}); + $('.perm_filter[value=none]').each(function(){this.checked = false; update_show($(this));}); }) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/changelog/changelog.html --- a/kallithea/templates/changelog/changelog.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/changelog/changelog.html Thu May 07 16:24:29 2015 +0200 @@ -89,11 +89,11 @@ %if c.statuses.get(cs.raw_id):
    %if c.statuses.get(cs.raw_id)[2]: - + %else: - + %endif diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/changelog/changelog_summary_data.html --- a/kallithea/templates/changelog/changelog_summary_data.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/changelog/changelog_summary_data.html Thu May 07 16:24:29 2015 +0200 @@ -17,7 +17,7 @@ %if c.statuses.get(cs.raw_id):
    %if c.statuses.get(cs.raw_id)[2]: - + %else: diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/changeset/changeset_file_comment.html --- a/kallithea/templates/changeset/changeset_file_comment.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/changeset/changeset_file_comment.html Thu May 07 16:24:29 2015 +0200 @@ -11,7 +11,7 @@ ${h.gravatar(co.author.email, size=20)}
    - ${co.author.username} + ${co.author.username_and_name}
    ${h.age(co.modified_at)} @@ -51,7 +51,13 @@ %endif
    + %if co.text: ${h.rst_w_mentions(co.text)|n} + %else: +
    +

    ${_('No comments.')}

    +
    + %endif
    diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/files/files_browser.html --- a/kallithea/templates/files/files_browser.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/files/files_browser.html Thu May 07 16:24:29 2015 +0200 @@ -47,7 +47,7 @@
    diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/pullrequests/pullrequest_show.html --- a/kallithea/templates/pullrequests/pullrequest_show.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/pullrequests/pullrequest_show.html Thu May 07 16:24:29 2015 +0200 @@ -3,11 +3,11 @@ <%namespace name="comment" file="/changeset/changeset_file_comment.html"/> <%block name="title"> - ${_('%s Pull Request #%s') % (c.repo_name, c.pull_request.pull_request_id)} + ${_('%s Pull Request %s') % (c.repo_name, c.pull_request.nice_id())} <%def name="breadcrumbs_links()"> - ${_('Pull request #%s from %s#%s') % (c.pull_request.pull_request_id, c.pull_request.org_repo.repo_name, c.cs_branch_name)} + ${_('Pull request %s from %s#%s') % (c.pull_request.nice_id(), c.pull_request.org_repo.repo_name, c.cs_branch_name)} <%block name="header_menu"> diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/templates/register.html --- a/kallithea/templates/register.html Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/templates/register.html Thu May 07 16:24:29 2015 +0200 @@ -33,7 +33,7 @@
    - ${h.password('password',class_="medium",autocomplete="off")} + ${h.password('password',class_="medium")}
    @@ -42,7 +42,7 @@
    - ${h.password('password_confirmation',class_="medium",autocomplete="off")} + ${h.password('password_confirmation',class_="medium")}
    diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/__init__.py --- a/kallithea/tests/__init__.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/__init__.py Thu May 07 16:24:29 2015 +0200 @@ -55,7 +55,7 @@ from kallithea.lib.compat import unittest from kallithea import is_windows from kallithea.model.db import User -from kallithea.tests.nose_parametrized import parameterized +from kallithea.tests.parameterized import parameterized from kallithea.lib.utils2 import safe_str diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/api/api_base.py --- a/kallithea/tests/api/api_base.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/api/api_base.py Thu May 07 16:24:29 2015 +0200 @@ -88,7 +88,7 @@ return gr -class BaseTestApi(object): +class _BaseTestApi(object): REPO = None REPO_TYPE = None diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/api/test_api_git.py --- a/kallithea/tests/api/test_api_git.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/api/test_api_git.py Thu May 07 16:24:29 2015 +0200 @@ -12,10 +12,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from kallithea.tests import * -from kallithea.tests.api.api_base import BaseTestApi +from kallithea.tests import TestController, GIT_REPO +from kallithea.tests.api.api_base import _BaseTestApi -class TestGitApi(BaseTestApi, TestController): +class TestGitApi(_BaseTestApi, TestController): REPO = GIT_REPO REPO_TYPE = 'git' diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/api/test_api_hg.py --- a/kallithea/tests/api/test_api_hg.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/api/test_api_hg.py Thu May 07 16:24:29 2015 +0200 @@ -12,10 +12,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from kallithea.tests import * -from kallithea.tests.api.api_base import BaseTestApi +from kallithea.tests import TestController, HG_REPO +from kallithea.tests.api.api_base import _BaseTestApi -class TestHgApi(BaseTestApi, TestController): +class TestHgApi(_BaseTestApi, TestController): REPO = HG_REPO REPO_TYPE = 'hg' diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/conftest.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/tests/conftest.py Thu May 07 16:24:29 2015 +0200 @@ -0,0 +1,29 @@ +import os +import sys + +import pkg_resources +from paste.deploy import loadapp +import pylons.test +from pylons.i18n.translation import _get_translator + + +def pytest_configure(): + path = os.getcwd() + sys.path.insert(0, path) + pkg_resources.working_set.add_entry(path) + pylons.test.pylonsapp = loadapp('config:test.ini', relative_to=path) + + # Setup the config and app_globals, only works if we can get + # to the config object + conf = getattr(pylons.test.pylonsapp, 'config') + if conf: + pylons.config._push_object(conf) + + if 'pylons.app_globals' in conf: + pylons.app_globals._push_object(conf['pylons.app_globals']) + + # Initialize a translator for tests that utilize i18n + translator = _get_translator(pylons.config.get('lang')) + pylons.translator._push_object(translator) + + return pylons.test.pylonsapp diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/fixtures/journal_dump.csv --- a/kallithea/tests/fixtures/journal_dump.csv Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/fixtures/journal_dump.csv Thu May 07 16:24:29 2015 +0200 @@ -1782,9 +1782,9 @@ 1846,3,demo,99,another-fork-to-check-code-review,"",user_commented_revision:fba17a64fa4978bfea19222da5e64a18cfddeecd,2012-11-06 04:15:29.032768 1847,3,demo,68,aaa-project,"",user_commented_revision:0c33fa58efc5a5541d8d3f1a3d3b77367e3d94f5,2012-11-06 04:17:16.091927 1848,3,demo,249,abcdefg,"",user_commented_revision:5d80e28538141e322b317168e2367fb03178d58c,2012-11-06 06:10:53.372505 -1849,3,demo,362,Marcin,"",started_following_repo,2012-11-06 10:45:38.505485 -1850,3,demo,362,Marcin,"",user_created_repo,2012-11-06 10:45:38.518969 -1851,3,demo,362,hidden/Marcin,"",user_updated_repo,2012-11-06 10:45:46.281581 +1849,3,demo,362,Username,"",started_following_repo,2012-11-06 10:45:38.505485 +1850,3,demo,362,Username,"",user_created_repo,2012-11-06 10:45:38.518969 +1851,3,demo,362,hidden/Username,"",user_updated_repo,2012-11-06 10:45:46.281581 1852,3,demo,177,blah,62.200.22.2,push:b369fb18c8d61fe0d3b14c417466680230cabe46,2012-11-06 10:47:55.655029 1853,3,demo,99,another-fork-to-check-code-review,"",user_commented_revision:d5422faf648cc589425cd3b0dbf1f6dbf93036a0,2012-11-06 13:12:05.517155 1854,3,demo,38,code-review-test,"",user_commented_revision:6d7db5794e8cad7da042b6ae6238116c6e59a4d2,2012-11-06 16:12:59.38977 diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/functional/test_admin_repos.py --- a/kallithea/tests/functional/test_admin_repos.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/functional/test_admin_repos.py Thu May 07 16:24:29 2015 +0200 @@ -26,7 +26,7 @@ return perm -class _BaseTest(TestController): +class _BaseTest(object): """ Write all tests here """ @@ -638,7 +638,7 @@ # repo must not be in filesystem ! self.assertFalse(os.path.isdir(os.path.join(TESTS_TMP_PATH, repo_name))) -class TestAdminReposControllerGIT(_BaseTest): +class TestAdminReposControllerGIT(TestController, _BaseTest): REPO = GIT_REPO REPO_TYPE = 'git' NEW_REPO = NEW_GIT_REPO @@ -646,7 +646,7 @@ OTHER_TYPE = 'hg' -class TestAdminReposControllerHG(_BaseTest): +class TestAdminReposControllerHG(TestController, _BaseTest): REPO = HG_REPO REPO_TYPE = 'hg' NEW_REPO = NEW_HG_REPO diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/functional/test_forks.py --- a/kallithea/tests/functional/test_forks.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/functional/test_forks.py Thu May 07 16:24:29 2015 +0200 @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- + +import unittest + from kallithea.tests import * from kallithea.tests.fixture import Fixture @@ -12,15 +15,7 @@ from kallithea.tests import * -class _BaseTest(TestController): - """ - Write all tests here - """ - REPO = None - REPO_TYPE = None - NEW_REPO = None - REPO_FORK = None - +class _BaseFixture(unittest.TestCase): @classmethod def setup_class(cls): pass @@ -40,6 +35,16 @@ Session().delete(self.u1) Session().commit() + +class _BaseTestCase(object): + """ + Write all tests here + """ + REPO = None + REPO_TYPE = None + NEW_REPO = None + REPO_FORK = None + def test_index(self): self.log_user() repo_name = self.REPO @@ -218,14 +223,14 @@ response.mustcontain('There are no forks yet') -class TestGIT(_BaseTest): +class TestGIT(TestController, _BaseTestCase, _BaseFixture): REPO = GIT_REPO NEW_REPO = NEW_GIT_REPO REPO_TYPE = 'git' REPO_FORK = GIT_FORK -class TestHG(_BaseTest): +class TestHG(TestController, _BaseTestCase, _BaseFixture): REPO = HG_REPO NEW_REPO = NEW_HG_REPO REPO_TYPE = 'hg' diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/functional/test_login.py --- a/kallithea/tests/functional/test_login.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/functional/test_login.py Thu May 07 16:24:29 2015 +0200 @@ -208,7 +208,7 @@ def test_register_ok(self): username = 'test_regular4' password = 'qweqwe' - email = 'marcin@test.com' + email = 'username@test.com' name = 'testname' lastname = 'testlastname' @@ -233,7 +233,7 @@ self.assertEqual(ret.admin, False) def test_forgot_password_wrong_mail(self): - bad_email = 'marcin@wrongmail.org' + bad_email = 'username@wrongmail.org' response = self.app.post( url(controller='login', action='password_reset'), {'email': bad_email, } @@ -250,7 +250,7 @@ username = 'test_password_reset_1' password = 'qweqwe' - email = 'marcin@python-works.com' + email = 'username@python-works.com' name = 'passwd' lastname = 'reset' diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/models/test_changeset_status.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/tests/models/test_changeset_status.py Thu May 07 16:24:29 2015 +0200 @@ -0,0 +1,40 @@ +from kallithea.tests import * +from kallithea.model.changeset_status import ChangesetStatusModel +from kallithea.model.db import ChangesetStatus as CS + +class CSM(object): # ChangesetStatusMock + + def __init__(self, status): + self.status = status + +class TestChangesetStatusCalculation(BaseTestCase): + + def setUp(self): + self.m = ChangesetStatusModel() + + @parameterized.expand([ + ('empty list', CS.STATUS_UNDER_REVIEW, []), + ('approve', CS.STATUS_APPROVED, [CSM(CS.STATUS_APPROVED)]), + ('approve2', CS.STATUS_APPROVED, [CSM(CS.STATUS_APPROVED), CSM(CS.STATUS_APPROVED)]), + ('approve_reject', CS.STATUS_REJECTED, [CSM(CS.STATUS_APPROVED), CSM(CS.STATUS_REJECTED)]), + ('approve_underreview', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_APPROVED), CSM(CS.STATUS_UNDER_REVIEW)]), + ('approve_notreviewed', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_APPROVED), CSM(CS.STATUS_NOT_REVIEWED)]), + ('underreview', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_UNDER_REVIEW), CSM(CS.STATUS_UNDER_REVIEW)]), + ('reject', CS.STATUS_REJECTED, [CSM(CS.STATUS_REJECTED)]), + ('reject_underreview', CS.STATUS_REJECTED, [CSM(CS.STATUS_REJECTED), CSM(CS.STATUS_UNDER_REVIEW)]), + ('reject_notreviewed', CS.STATUS_REJECTED, [CSM(CS.STATUS_REJECTED), CSM(CS.STATUS_NOT_REVIEWED)]), + ('notreviewed', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_NOT_REVIEWED)]), + ('approve_none', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_APPROVED), None]), + ('approve2_none', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_APPROVED), CSM(CS.STATUS_APPROVED), None]), + ('approve_reject_none', CS.STATUS_REJECTED, [CSM(CS.STATUS_APPROVED), CSM(CS.STATUS_REJECTED), None]), + ('approve_underreview_none', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_APPROVED), CSM(CS.STATUS_UNDER_REVIEW), None]), + ('approve_notreviewed_none', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_APPROVED), CSM(CS.STATUS_NOT_REVIEWED), None]), + ('underreview_none', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_UNDER_REVIEW), CSM(CS.STATUS_UNDER_REVIEW), None]), + ('reject_none', CS.STATUS_REJECTED, [CSM(CS.STATUS_REJECTED), None]), + ('reject_underreview_none', CS.STATUS_REJECTED, [CSM(CS.STATUS_REJECTED), CSM(CS.STATUS_UNDER_REVIEW), None]), + ('reject_notreviewed_none', CS.STATUS_REJECTED, [CSM(CS.STATUS_REJECTED), CSM(CS.STATUS_NOT_REVIEWED), None]), + ('notreviewed_none', CS.STATUS_UNDER_REVIEW, [CSM(CS.STATUS_NOT_REVIEWED), None]), + ]) + def test_result(self, name, expected_result, statuses): + result = self.m._calculate_status(statuses) + self.assertEqual(result, expected_result) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/models/test_user_group_permissions_on_repo_groups.py --- a/kallithea/tests/models/test_user_group_permissions_on_repo_groups.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/models/test_user_group_permissions_on_repo_groups.py Thu May 07 16:24:29 2015 +0200 @@ -1,11 +1,9 @@ import functools -from kallithea.tests import * from kallithea.model.repo_group import RepoGroupModel from kallithea.model.db import RepoGroup from kallithea.model.meta import Session -from nose.tools import with_setup from kallithea.tests.models.common import _create_project_tree, check_tree_perms, \ _get_perms, _check_expected_count, expected_count, _destroy_project_tree from kallithea.model.user_group import UserGroupModel @@ -26,6 +24,13 @@ repo_group = RepoGroup.get_by_group_name(group_name=group_name) if not repo_group: raise Exception('Cannot get group %s' % group_name) + + # Start with a baseline that current group can read recursive + perms_updates = [[test_u2_gr_id, 'group.read', 'users_group']] + RepoGroupModel()._update_permissions(repo_group, + perms_updates=perms_updates, + recursive='all', check_perms=False) + perms_updates = [[test_u2_gr_id, perm, 'users_group']] RepoGroupModel()._update_permissions(repo_group, perms_updates=perms_updates, @@ -53,9 +58,9 @@ def teardown_module(): _destroy_project_tree(test_u2_id) + fixture.destroy_user_group('perms_group_1') -@with_setup(permissions_setup_func) def test_user_permissions_on_group_without_recursive_mode(): # set permission to g0 non-recursive mode recursive = 'none' @@ -75,7 +80,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_without_recursive_mode_subgroup(): # set permission to g0 non-recursive mode recursive = 'none' @@ -95,7 +99,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_mode(): # set permission to g0 recursive mode, all children including @@ -115,7 +118,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_mode_inner_group(): ## set permission to g0_3 group to none recursive = 'all' @@ -133,7 +135,6 @@ yield check_tree_perms, name, perm, group, 'group.none' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_mode_deepest(): ## set permission to g0_3 group to none recursive = 'all' @@ -151,7 +152,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_mode_only_with_repos(): ## set permission to g0_3 group to none recursive = 'all' @@ -168,7 +168,7 @@ for name, perm in items: yield check_tree_perms, name, perm, group, 'group.admin' -@with_setup(permissions_setup_func) + def test_user_permissions_on_group_with_recursive_mode_on_repos(): # set permission to g0/g0_1 with recursive mode on just repositories recursive = 'repos' @@ -192,7 +192,7 @@ old_perm = perm yield check_tree_perms, name, perm, group, old_perm -@with_setup(permissions_setup_func) + def test_user_permissions_on_group_with_recursive_mode_on_repo_groups(): # set permission to g0/g0_1 with recursive mode on just repository groups recursive = 'groups' diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/models/test_user_groups.py --- a/kallithea/tests/models/test_user_groups.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/models/test_user_groups.py Thu May 07 16:24:29 2015 +0200 @@ -1,6 +1,6 @@ from kallithea.model.db import User -from kallithea.tests import * +from kallithea.tests import BaseTestCase, parameterized, TEST_USER_REGULAR_LOGIN from kallithea.tests.fixture import Fixture from kallithea.model.user_group import UserGroupModel @@ -18,7 +18,6 @@ fixture.destroy_user_group(gr) Session().commit() - @parameterized.expand([ ([], [], [], [], []), ([], ['regular'], [], [], ['regular']), # no changes of regular diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/models/test_user_permissions_on_repo_groups.py --- a/kallithea/tests/models/test_user_permissions_on_repo_groups.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/models/test_user_permissions_on_repo_groups.py Thu May 07 16:24:29 2015 +0200 @@ -1,11 +1,9 @@ import functools -from kallithea.tests import * from kallithea.model.repo_group import RepoGroupModel from kallithea.model.db import RepoGroup, User from kallithea.model.meta import Session -from nose.tools import with_setup from kallithea.tests.models.common import _create_project_tree, check_tree_perms, \ _get_perms, _check_expected_count, expected_count, _destroy_project_tree @@ -22,7 +20,6 @@ """ if not user_id: user_id = test_u1_id - # called by the @with_setup decorator also reset the default user stuff permissions_setup_func(group_name, perm, recursive, user_id=User.get_default_user().user_id) @@ -30,12 +27,19 @@ if not repo_group: raise Exception('Cannot get group %s' % group_name) + # Start with a baseline that current group can read recursive + perms_updates = [[user_id, 'group.read', 'user']] + RepoGroupModel()._update_permissions(repo_group, + perms_updates=perms_updates, + recursive='all', check_perms=False) + perms_updates = [[user_id, perm, 'user']] RepoGroupModel()._update_permissions(repo_group, perms_updates=perms_updates, recursive=recursive, check_perms=False) Session().commit() + def setup_module(): global test_u1_id, _get_repo_perms, _get_group_perms test_u1 = _create_project_tree() @@ -51,7 +55,6 @@ _destroy_project_tree(test_u1_id) -@with_setup(permissions_setup_func) def test_user_permissions_on_group_without_recursive_mode(): # set permission to g0 non-recursive mode recursive = 'none' @@ -71,7 +74,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_without_recursive_mode_subgroup(): # set permission to g0 non-recursive mode recursive = 'none' @@ -91,7 +93,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_mode(): # set permission to g0 recursive mode, all children including @@ -111,7 +112,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_mode_for_default_user(): # set permission to g0 recursive mode, all children including @@ -139,7 +139,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_mode_inner_group(): ## set permission to g0_3 group to none recursive = 'all' @@ -157,7 +156,6 @@ yield check_tree_perms, name, perm, group, 'group.none' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_mode_deepest(): ## set permission to g0_3 group to none recursive = 'all' @@ -175,7 +173,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_mode_only_with_repos(): ## set permission to g0_3 group to none recursive = 'all' @@ -193,7 +190,6 @@ yield check_tree_perms, name, perm, group, 'group.admin' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_repo_mode_for_default_user(): # set permission to g0/g0_1 recursive repos only mode, all children including # other repos should have this permission now set, inner groups are excluded! @@ -228,7 +224,6 @@ yield check_tree_perms, name, perm, group, old_perm -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_repo_mode_inner_group(): ## set permission to g0_3 group to none, with recursive repos only recursive = 'repos' @@ -253,7 +248,6 @@ yield check_tree_perms, name, perm, group, old_perm -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_group_mode_for_default_user(): # set permission to g0/g0_1 with recursive groups only mode, all children including # other groups should have this permission now set. repositories should @@ -281,7 +275,6 @@ yield check_tree_perms, name, perm, group, 'group.write' -@with_setup(permissions_setup_func) def test_user_permissions_on_group_with_recursive_group_mode_inner_group(): ## set permission to g0_3 group to none, with recursive mode for groups only recursive = 'groups' diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/nose_parametrized.py --- a/kallithea/tests/nose_parametrized.py Thu May 07 16:23:45 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,238 +0,0 @@ -import re -import new -import inspect -import logging -import logging.handlers -from functools import wraps - -from nose.tools import nottest -from unittest import TestCase - - -def _terrible_magic_get_defining_classes(): - """ Returns the set of parent classes of the class currently being defined. - Will likely only work if called from the ``parameterized`` decorator. - This function is entirely @brandon_rhodes's fault, as he suggested - the implementation: http://stackoverflow.com/a/8793684/71522 - """ - stack = inspect.stack() - if len(stack) <= 4: - return [] - frame = stack[3] - code_context = frame[4][0].strip() - if not code_context.startswith("class "): - return [] - _, parents = code_context.split("(", 1) - parents, _ = parents.rsplit(")", 1) - return eval("[" + parents + "]", frame[0].f_globals, frame[0].f_locals) - - -def parameterized(input): - """ Parameterize a test case: - >>> add1_tests = [(1, 2), (2, 3)] - >>> class TestFoo(object): - ... @parameterized(add1_tests) - ... def test_add1(self, input, expected): - ... assert_equal(add1(input), expected) - >>> @parameterized(add1_tests) - ... def test_add1(input, expected): - ... assert_equal(add1(input), expected) - >>> - """ - - if not hasattr(input, "__iter__"): - raise ValueError("expected iterable input; got %r" % (input,)) - - def parameterized_helper(f): - attached_instance_method = [False] - - parent_classes = _terrible_magic_get_defining_classes() - if any(issubclass(cls, TestCase) for cls in parent_classes): - raise Exception("Warning: '@parameterized' tests won't work " - "inside subclasses of 'TestCase' - use " - "'@parameterized.expand' instead") - - @wraps(f) - def parameterized_helper_method(self=None): - if self is not None and not attached_instance_method[0]: - # confusingly, we need to create a named instance method and - # attach that to the class... - cls = self.__class__ - im_f = new.instancemethod(f, None, cls) - setattr(cls, f.__name__, im_f) - attached_instance_method[0] = True - for args in input: - if isinstance(args, basestring): - args = [args] - # ... then pull that named instance method off, turning it into - # a bound method ... - if self is not None: - args = [getattr(self, f.__name__)] + list(args) - else: - args = [f] + list(args) - # ... then yield that as a tuple. If those steps aren't - # followed precicely, Nose gets upset and doesn't run the test - # or doesn't run setup methods. - yield tuple(args) - - f.__name__ = "_helper_for_%s" % (f.__name__,) - parameterized_helper_method.parameterized_input = input - parameterized_helper_method.parameterized_func = f - return parameterized_helper_method - - return parameterized_helper - - -def to_safe_name(s): - return re.sub("[^a-zA-Z0-9_]", "", s) - - -def parameterized_expand_helper(func_name, func, args): - def parameterized_expand_helper_helper(self=()): - if self != (): - self = (self,) - return func(*(self + args)) - parameterized_expand_helper_helper.__name__ = str(func_name) - return parameterized_expand_helper_helper - - -def parameterized_expand(input): - """ A "brute force" method of parameterizing test cases. Creates new test - cases and injects them into the namespace that the wrapped function - is being defined in. Useful for parameterizing tests in subclasses - of 'UnitTest', where Nose test generators don't work. - - >>> @parameterized.expand([("foo", 1, 2)]) - ... def test_add1(name, input, expected): - ... actual = add1(input) - ... assert_equal(actual, expected) - ... - >>> locals() - ... 'test_add1_foo_0': ... - >>> - """ - - def parameterized_expand_wrapper(f): - stack = inspect.stack() - frame = stack[1] - frame_locals = frame[0].f_locals - - base_name = f.__name__ - for num, args in enumerate(input): - name_suffix = "_%s" % (num,) - if len(args) > 0 and isinstance(args[0], basestring): - name_suffix += "_" + to_safe_name(args[0]) - name = base_name + name_suffix - new_func = parameterized_expand_helper(name, f, args) - frame_locals[name] = new_func - return nottest(f) - return parameterized_expand_wrapper - -parameterized.expand = parameterized_expand - - -def assert_contains(haystack, needle): - if needle not in haystack: - raise AssertionError("%r not in %r" % (needle, haystack)) - - -def assert_not_contains(haystack, needle): - if needle in haystack: - raise AssertionError("%r in %r" % (needle, haystack)) - - -def imported_from_test(): - """ Returns true if it looks like this module is being imported by unittest - or nose. """ - import re - import inspect - nose_re = re.compile(r"\bnose\b") - unittest_re = re.compile(r"\bunittest2?\b") - for frame in inspect.stack(): - file = frame[1] - if nose_re.search(file) or unittest_re.search(file): - return True - return False - - -def assert_raises(func, exc_type, str_contains=None, repr_contains=None): - try: - func() - except exc_type, e: - if str_contains is not None and str_contains not in str(e): - raise AssertionError("%s raised, but %r does not contain %r" - % (exc_type, str(e), str_contains)) - if repr_contains is not None and repr_contains not in repr(e): - raise AssertionError("%s raised, but %r does not contain %r" - % (exc_type, repr(e), repr_contains)) - return e - else: - raise AssertionError("%s not raised" % (exc_type,)) - - -log_handler = None - - -def setup_logging(): - """ Configures a log handler which will capure log messages during a test. - The ``logged_messages`` and ``assert_no_errors_logged`` functions can be - used to make assertions about these logged messages. - - For example:: - - from ensi_common.testing import ( - setup_logging, teardown_logging, assert_no_errors_logged, - assert_logged, - ) - - class TestWidget(object): - def setup(self): - setup_logging() - - def teardown(self): - assert_no_errors_logged() - teardown_logging() - - def test_that_will_fail(self): - log.warning("this warning message will trigger a failure") - - def test_that_will_pass(self): - log.info("but info messages are ok") - assert_logged("info messages are ok") - """ - - global log_handler - if log_handler is not None: - logging.getLogger().removeHandler(log_handler) - log_handler = logging.handlers.BufferingHandler(1000) - formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s") - log_handler.setFormatter(formatter) - logging.getLogger().addHandler(log_handler) - - -def teardown_logging(): - global log_handler - if log_handler is not None: - logging.getLogger().removeHandler(log_handler) - log_handler = None - - -def logged_messages(): - assert log_handler, "setup_logging not called" - return [(log_handler.format(record), record) for record in log_handler.buffer] - - -def assert_no_errors_logged(): - for _, record in logged_messages(): - if record.levelno >= logging.WARNING: - # Assume that the nose log capture plugin is being used, so it will - # show the exception. - raise AssertionError("an unexpected error was logged") - - -def assert_logged(expected_msg_contents): - for msg, _ in logged_messages(): - if expected_msg_contents in msg: - return - raise AssertionError("no logged message contains %r" - % (expected_msg_contents,)) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/other/manual_test_vcs_operations.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/tests/other/manual_test_vcs_operations.py Thu May 07 16:24:29 2015 +0200 @@ -0,0 +1,536 @@ +# -*- 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.tests.test_scm_operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Test suite for making push/pull operations. + +Run it in two terminals:: + paster serve test.ini + KALLITHEA_WHOOSH_TEST_DISABLE=1 KALLITHEA_NO_TMP_PATH=1 nosetests kallithea/tests/other/manual_test_vcs_operations.py + +You must have git > 1.8.1 for tests to work fine + +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 30, 2010 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH, and others. +:license: GPLv3, see LICENSE.md for more details. + +""" + +import tempfile +import time +from os.path import join as jn + +from tempfile import _RandomNameSequence +from subprocess import Popen, PIPE + +from kallithea.tests import * +from kallithea.model.db import User, Repository, UserIpMap, CacheInvalidation +from kallithea.model.meta import Session +from kallithea.model.repo import RepoModel +from kallithea.model.user import UserModel + +DEBUG = True +HOST = '127.0.0.1:5000' # test host + + +class Command(object): + + def __init__(self, cwd): + self.cwd = cwd + + def execute(self, cmd, *args): + """ + Runs command on the system with given ``args``. + """ + + command = cmd + ' ' + ' '.join(args) + if DEBUG: + print '*** CMD %s ***' % command + p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, cwd=self.cwd) + stdout, stderr = p.communicate() + if DEBUG: + print 'stdout:', repr(stdout) + print 'stderr:', repr(stderr) + return stdout, stderr + + +def _get_tmp_dir(): + return tempfile.mkdtemp(prefix='rc_integration_test') + + +def _construct_url(repo, dest=None, **kwargs): + if dest is None: + #make temp clone + dest = _get_tmp_dir() + params = { + 'user': TEST_USER_ADMIN_LOGIN, + 'passwd': TEST_USER_ADMIN_PASS, + 'host': HOST, + 'cloned_repo': repo, + 'dest': dest + } + params.update(**kwargs) + if params['user'] and params['passwd']: + _url = 'http://%(user)s:%(passwd)s@%(host)s/%(cloned_repo)s %(dest)s' % params + else: + _url = 'http://(host)s/%(cloned_repo)s %(dest)s' % params + return _url + + +def _add_files_and_push(vcs, DEST, **kwargs): + """ + Generate some files, add it to DEST repo and push back + vcs is git or hg and defines what VCS we want to make those files for + + :param vcs: + :param DEST: + """ + # commit some stuff into this repo + cwd = path = jn(DEST) + #added_file = jn(path, '%ssetupążźć.py' % _RandomNameSequence().next()) + added_file = jn(path, '%ssetup.py' % _RandomNameSequence().next()) + Command(cwd).execute('touch %s' % added_file) + Command(cwd).execute('%s add %s' % (vcs, added_file)) + + for i in xrange(kwargs.get('files_no', 3)): + cmd = """echo 'added_line%s' >> %s""" % (i, added_file) + Command(cwd).execute(cmd) + author_str = 'User ǝɯɐᴎ ' + if vcs == 'hg': + cmd = """hg commit -m 'commited new %s' -u '%s' %s """ % ( + i, author_str, added_file + ) + elif vcs == 'git': + cmd = """EMAIL="me@email.com" git commit -m 'commited new %s' --author '%s' %s """ % ( + i, author_str, added_file + ) + Command(cwd).execute(cmd) + + # PUSH it back + _REPO = None + if vcs == 'hg': + _REPO = HG_REPO + elif vcs == 'git': + _REPO = GIT_REPO + + kwargs['dest'] = '' + clone_url = _construct_url(_REPO, **kwargs) + if 'clone_url' in kwargs: + clone_url = kwargs['clone_url'] + stdout = stderr = None + if vcs == 'hg': + stdout, stderr = Command(cwd).execute('hg push --verbose', clone_url) + elif vcs == 'git': + stdout, stderr = Command(cwd).execute('git push --verbose', clone_url + " master") + + return stdout, stderr + + +def set_anonymous_access(enable=True): + user = User.get_by_username(User.DEFAULT_USER) + user.active = enable + Session().add(user) + Session().commit() + print '\tanonymous access is now:', enable + if enable != User.get_by_username(User.DEFAULT_USER).active: + raise Exception('Cannot set anonymous access') + + +#============================================================================== +# TESTS +#============================================================================== + + +def _check_proper_git_push(stdout, stderr): + #WTF Git stderr is output ?! + assert 'fatal' not in stderr + assert 'rejected' not in stderr + assert 'Pushing to' in stderr + assert 'master -> master' in stderr + + +class TestVCSOperations(BaseTestCase): + + @classmethod + def setup_class(cls): + #DISABLE ANONYMOUS ACCESS + set_anonymous_access(False) + + def setUp(self): + r = Repository.get_by_repo_name(GIT_REPO) + Repository.unlock(r) + r.enable_locking = False + Session().add(r) + Session().commit() + + r = Repository.get_by_repo_name(HG_REPO) + Repository.unlock(r) + r.enable_locking = False + Session().add(r) + Session().commit() + + def test_clone_hg_repo_by_admin(self): + clone_url = _construct_url(HG_REPO) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + + assert 'requesting all changes' in stdout + assert 'adding changesets' in stdout + assert 'adding manifests' in stdout + assert 'adding file changes' in stdout + + assert stderr == '' + + def test_clone_git_repo_by_admin(self): + clone_url = _construct_url(GIT_REPO) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + + assert 'Cloning into' in stdout + stderr + assert stderr == '' or stdout == '' + + def test_clone_wrong_credentials_hg(self): + clone_url = _construct_url(HG_REPO, passwd='bad!') + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + assert 'abort: authorization failed' in stderr + + def test_clone_wrong_credentials_git(self): + clone_url = _construct_url(GIT_REPO, passwd='bad!') + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + assert 'fatal: Authentication failed' in stderr + + def test_clone_git_dir_as_hg(self): + clone_url = _construct_url(GIT_REPO) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + assert 'HTTP Error 404: Not Found' in stderr + + def test_clone_hg_repo_as_git(self): + clone_url = _construct_url(HG_REPO) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + assert 'not found' in stderr + + def test_clone_non_existing_path_hg(self): + clone_url = _construct_url('trololo') + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + assert 'HTTP Error 404: Not Found' in stderr + + def test_clone_non_existing_path_git(self): + clone_url = _construct_url('trololo') + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + assert 'not found' in stderr + + def test_push_new_file_hg(self): + DEST = _get_tmp_dir() + clone_url = _construct_url(HG_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + + stdout, stderr = _add_files_and_push('hg', DEST) + + assert 'pushing to' in stdout + assert 'Repository size' in stdout + assert 'Last revision is now' in stdout + + def test_push_new_file_git(self): + DEST = _get_tmp_dir() + clone_url = _construct_url(GIT_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + + # commit some stuff into this repo + stdout, stderr = _add_files_and_push('git', DEST) + + print [(x.repo_full_path,x.repo_path) for x in Repository.get_all()] + _check_proper_git_push(stdout, stderr) + + def test_push_invalidates_cache_hg(self): + key = CacheInvalidation.query().filter(CacheInvalidation.cache_key + ==HG_REPO).scalar() + if not key: + key = CacheInvalidation(HG_REPO, HG_REPO) + + key.cache_active = True + Session().add(key) + Session().commit() + + DEST = _get_tmp_dir() + clone_url = _construct_url(HG_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + + stdout, stderr = _add_files_and_push('hg', DEST, files_no=1) + + key = CacheInvalidation.query().filter(CacheInvalidation.cache_key + ==HG_REPO).one() + self.assertEqual(key.cache_active, False) + + def test_push_invalidates_cache_git(self): + key = CacheInvalidation.query().filter(CacheInvalidation.cache_key + ==GIT_REPO).scalar() + if not key: + key = CacheInvalidation(GIT_REPO, GIT_REPO) + + key.cache_active = True + Session().add(key) + Session().commit() + + DEST = _get_tmp_dir() + clone_url = _construct_url(GIT_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + + # commit some stuff into this repo + stdout, stderr = _add_files_and_push('git', DEST, files_no=1) + _check_proper_git_push(stdout, stderr) + + key = CacheInvalidation.query().filter(CacheInvalidation.cache_key + ==GIT_REPO).one() + print CacheInvalidation.get_all() + self.assertEqual(key.cache_active, False) + + def test_push_wrong_credentials_hg(self): + DEST = _get_tmp_dir() + clone_url = _construct_url(HG_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + + stdout, stderr = _add_files_and_push('hg', DEST, user='bad', + passwd='name') + + assert 'abort: authorization failed' in stderr + + def test_push_wrong_credentials_git(self): + DEST = _get_tmp_dir() + clone_url = _construct_url(GIT_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + + stdout, stderr = _add_files_and_push('git', DEST, user='bad', + passwd='name') + + assert 'fatal: Authentication failed' in stderr + + def test_push_back_to_wrong_url_hg(self): + DEST = _get_tmp_dir() + clone_url = _construct_url(HG_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + + stdout, stderr = _add_files_and_push('hg', DEST, + clone_url='http://127.0.0.1:5000/tmp',) + + assert 'HTTP Error 404: Not Found' in stderr + + def test_push_back_to_wrong_url_git(self): + DEST = _get_tmp_dir() + clone_url = _construct_url(GIT_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + + stdout, stderr = _add_files_and_push('git', DEST, + clone_url='http://127.0.0.1:5000/tmp',) + + assert 'not found' in stderr + + def test_clone_and_create_lock_hg(self): + # enable locking + r = Repository.get_by_repo_name(HG_REPO) + r.enable_locking = True + Session().add(r) + Session().commit() + # clone + clone_url = _construct_url(HG_REPO) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + + #check if lock was made + r = Repository.get_by_repo_name(HG_REPO) + assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id + + def test_clone_and_create_lock_git(self): + # enable locking + r = Repository.get_by_repo_name(GIT_REPO) + r.enable_locking = True + Session().add(r) + Session().commit() + # clone + clone_url = _construct_url(GIT_REPO) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + + #check if lock was made + r = Repository.get_by_repo_name(GIT_REPO) + assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id + + def test_clone_after_repo_was_locked_hg(self): + #lock repo + r = Repository.get_by_repo_name(HG_REPO) + Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) + #pull fails since repo is locked + clone_url = _construct_url(HG_REPO) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" + % (HG_REPO, TEST_USER_ADMIN_LOGIN)) + assert msg in stderr + + def test_clone_after_repo_was_locked_git(self): + #lock repo + r = Repository.get_by_repo_name(GIT_REPO) + Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) + #pull fails since repo is locked + clone_url = _construct_url(GIT_REPO) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + msg = ("""The requested URL returned error: 423""") + assert msg in stderr + + def test_push_on_locked_repo_by_other_user_hg(self): + #clone some temp + DEST = _get_tmp_dir() + clone_url = _construct_url(HG_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + + #lock repo + r = Repository.get_by_repo_name(HG_REPO) + # let this user actually push ! + RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, + perm='repository.write') + Session().commit() + Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) + + #push fails repo is locked by other user ! + stdout, stderr = _add_files_and_push('hg', DEST, + user=TEST_USER_REGULAR_LOGIN, + passwd=TEST_USER_REGULAR_PASS) + msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" + % (HG_REPO, TEST_USER_ADMIN_LOGIN)) + assert msg in stderr + + def test_push_on_locked_repo_by_other_user_git(self): + #clone some temp + DEST = _get_tmp_dir() + clone_url = _construct_url(GIT_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + + #lock repo + r = Repository.get_by_repo_name(GIT_REPO) + # let this user actually push ! + RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, + perm='repository.write') + Session().commit() + Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) + + #push fails repo is locked by other user ! + stdout, stderr = _add_files_and_push('git', DEST, + user=TEST_USER_REGULAR_LOGIN, + passwd=TEST_USER_REGULAR_PASS) + err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN) + assert err in stderr + + #TODO: fix this somehow later on Git, Git is stupid and even if we throw + #back 423 to it, it makes ANOTHER request and we fail there with 405 :/ + + msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" + % (GIT_REPO, TEST_USER_ADMIN_LOGIN)) + #msg = "405 Method Not Allowed" + #assert msg in stderr + + def test_push_unlocks_repository_hg(self): + # enable locking + r = Repository.get_by_repo_name(HG_REPO) + r.enable_locking = True + Session().add(r) + Session().commit() + #clone some temp + DEST = _get_tmp_dir() + clone_url = _construct_url(HG_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + + #check for lock repo after clone + r = Repository.get_by_repo_name(HG_REPO) + uid = User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id + assert r.locked[0] == uid + + #push is ok and repo is now unlocked + stdout, stderr = _add_files_and_push('hg', DEST) + assert ('remote: Released lock on repo `%s`' % HG_REPO) in stdout + #we need to cleanup the Session Here ! + Session.remove() + r = Repository.get_by_repo_name(HG_REPO) + assert r.locked == [None, None] + + #TODO: fix me ! somehow during tests hooks don't get called on Git + def test_push_unlocks_repository_git(self): + # enable locking + r = Repository.get_by_repo_name(GIT_REPO) + r.enable_locking = True + Session().add(r) + Session().commit() + #clone some temp + DEST = _get_tmp_dir() + clone_url = _construct_url(GIT_REPO, dest=DEST) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + + #check for lock repo after clone + r = Repository.get_by_repo_name(GIT_REPO) + assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id + + #push is ok and repo is now unlocked + stdout, stderr = _add_files_and_push('git', DEST) + _check_proper_git_push(stdout, stderr) + + #assert ('remote: Released lock on repo `%s`' % GIT_REPO) in stdout + #we need to cleanup the Session Here ! + Session.remove() + r = Repository.get_by_repo_name(GIT_REPO) + assert r.locked == [None, None] + + def test_ip_restriction_hg(self): + user_model = UserModel() + try: + user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') + Session().commit() + clone_url = _construct_url(HG_REPO) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + assert 'abort: HTTP Error 403: Forbidden' in stderr + finally: + #release IP restrictions + for ip in UserIpMap.getAll(): + UserIpMap.delete(ip.ip_id) + Session().commit() + + time.sleep(2) + clone_url = _construct_url(HG_REPO) + stdout, stderr = Command('/tmp').execute('hg clone', clone_url) + + assert 'requesting all changes' in stdout + assert 'adding changesets' in stdout + assert 'adding manifests' in stdout + assert 'adding file changes' in stdout + + assert stderr == '' + + def test_ip_restriction_git(self): + user_model = UserModel() + try: + user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') + Session().commit() + clone_url = _construct_url(GIT_REPO) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + msg = ("""The requested URL returned error: 403""") + assert msg in stderr + finally: + #release IP restrictions + for ip in UserIpMap.getAll(): + UserIpMap.delete(ip.ip_id) + Session().commit() + + time.sleep(2) + clone_url = _construct_url(GIT_REPO) + stdout, stderr = Command('/tmp').execute('git clone', clone_url) + + assert 'Cloning into' in stdout + stderr + assert stderr == '' or stdout == '' diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/other/test_libs.py --- a/kallithea/tests/other/test_libs.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/other/test_libs.py Thu May 07 16:24:29 2015 +0200 @@ -37,9 +37,9 @@ TEST_URLS = [ ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], '%s://127.0.0.1' % proto), - ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], + ('%s://username@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], '%s://127.0.0.1' % proto), - ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], + ('%s://username:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], '%s://127.0.0.1' % proto), ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'], '%s://127.0.0.1:8080' % proto), @@ -54,9 +54,9 @@ TEST_URLS += [ ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], '%s://127.0.0.1' % proto), - ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], + ('%s://username@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], '%s://127.0.0.1' % proto), - ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], + ('%s://username:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], '%s://127.0.0.1' % proto), ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'], '%s://127.0.0.1:8080' % proto), @@ -105,16 +105,16 @@ def test_mention_extractor(self): from kallithea.lib.utils2 import extract_mentioned_users sample = ( - "@first hi there @marcink here's my email marcin@email.com " + "@first hi there @world here's my email username@email.com " "@lukaszb check @one_more22 it pls @ ttwelve @D[] @one@two@three " - "@MARCIN @maRCiN @2one_more22 @john please see this http://org.pl " + "@UPPER @cAmEL @2one_more22 @john please see this http://org.pl " "@marian.user just do it @marco-polo and next extract @marco_polo " "user.dot hej ! not-needed maril@domain.org" ) s = sorted([ - '2one_more22', 'first', 'marcink', 'lukaszb', 'one', 'one_more22', 'MARCIN', 'maRCiN', 'john', - 'marian.user', 'marco-polo', 'marco_polo'], key=lambda k: k.lower()) + '2one_more22', 'first', 'lukaszb', 'one', 'one_more22', 'UPPER', 'cAmEL', 'john', + 'marian.user', 'marco-polo', 'marco_polo', 'world'], key=lambda k: k.lower()) self.assertEqual(s, extract_mentioned_users(sample)) @parameterized.expand([ @@ -251,23 +251,23 @@ @parameterized.expand([ (Repository.DEFAULT_CLONE_URI, 'group/repo1', {}, '', 'http://vps1:8000/group/repo1'), - (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'marcink'}, '', 'http://marcink@vps1:8000/group/repo1'), - (Repository.DEFAULT_CLONE_URI, 'group/repo1', {}, '/rc', 'http://vps1:8000/rc/group/repo1'), - (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/rc', 'http://user@vps1:8000/rc/group/repo1'), - (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'marcink'}, '/rc', 'http://marcink@vps1:8000/rc/group/repo1'), - (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/rc/', 'http://user@vps1:8000/rc/group/repo1'), - (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'marcink'}, '/rc/', 'http://marcink@vps1:8000/rc/group/repo1'), + (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'username'}, '', 'http://username@vps1:8000/group/repo1'), + (Repository.DEFAULT_CLONE_URI, 'group/repo1', {}, '/prefix', 'http://vps1:8000/prefix/group/repo1'), + (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/prefix', 'http://user@vps1:8000/prefix/group/repo1'), + (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'username'}, '/prefix', 'http://username@vps1:8000/prefix/group/repo1'), + (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/prefix/', 'http://user@vps1:8000/prefix/group/repo1'), + (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'username'}, '/prefix/', 'http://username@vps1:8000/prefix/group/repo1'), ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', {}, '', 'http://vps1:8000/_23'), - ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'marcink'}, '', 'http://marcink@vps1:8000/_23'), - ('http://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'marcink'}, '', 'http://marcink@vps1:8000/_23'), - ('http://{netloc}/_{repoid}', 'group/repo1', {'user': 'marcink'}, '', 'http://vps1:8000/_23'), - ('https://{user}@proxy1.server.com/{repo}', 'group/repo1', {'user': 'marcink'}, '', 'https://marcink@proxy1.server.com/group/repo1'), + ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'username'}, '', 'http://username@vps1:8000/_23'), + ('http://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'username'}, '', 'http://username@vps1:8000/_23'), + ('http://{netloc}/_{repoid}', 'group/repo1', {'user': 'username'}, '', 'http://vps1:8000/_23'), + ('https://{user}@proxy1.server.com/{repo}', 'group/repo1', {'user': 'username'}, '', 'https://username@proxy1.server.com/group/repo1'), ('https://{user}@proxy1.server.com/{repo}', 'group/repo1', {}, '', 'https://proxy1.server.com/group/repo1'), - ('https://proxy1.server.com/{user}/{repo}', 'group/repo1', {'user': 'marcink'}, '', 'https://proxy1.server.com/marcink/group/repo1'), + ('https://proxy1.server.com/{user}/{repo}', 'group/repo1', {'user': 'username'}, '', 'https://proxy1.server.com/username/group/repo1'), ]) def test_clone_url_generator(self, tmpl, repo_name, overrides, prefix, expected): from kallithea.lib.utils2 import get_clone_url - clone_url = get_clone_url(uri_tmpl=tmpl, qualifed_home_url='http://vps1:8000'+prefix, + clone_url = get_clone_url(uri_tmpl=tmpl, qualified_home_url='http://vps1:8000'+prefix, repo_name=repo_name, repo_id=23, **overrides) self.assertEqual(clone_url, expected) @@ -366,7 +366,7 @@ ("/_21/foobar", '21'), ("_21/121", '21'), ("/_21/_12", '21'), - ("_21/rc/foo", '21'), + ("_21/prefix/foo", '21'), ]) def test_get_repo_by_id(self, test, expected): from kallithea.lib.utils import _extract_id_from_repo_name diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/other/test_vcs_operations.py --- a/kallithea/tests/other/test_vcs_operations.py Thu May 07 16:23:45 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,533 +0,0 @@ -# -*- 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.tests.test_scm_operations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Test suite for making push/pull operations. -Run using after doing paster serve test.ini:: - KALLITHEA_WHOOSH_TEST_DISABLE=1 KALLITHEA_NO_TMP_PATH=1 nosetests kallithea/tests/other/test_vcs_operations.py - -You must have git > 1.8.1 for tests to work fine - -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 30, 2010 -:author: marcink -:copyright: (c) 2013 RhodeCode GmbH, and others. -:license: GPLv3, see LICENSE.md for more details. - -""" - -import tempfile -import time -from os.path import join as jn - -from tempfile import _RandomNameSequence -from subprocess import Popen, PIPE - -from kallithea.tests import * -from kallithea.model.db import User, Repository, UserIpMap, CacheInvalidation -from kallithea.model.meta import Session -from kallithea.model.repo import RepoModel -from kallithea.model.user import UserModel - -DEBUG = True -HOST = '127.0.0.1:5000' # test host - - -class Command(object): - - def __init__(self, cwd): - self.cwd = cwd - - def execute(self, cmd, *args): - """ - Runs command on the system with given ``args``. - """ - - command = cmd + ' ' + ' '.join(args) - if DEBUG: - print '*** CMD %s ***' % command - p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, cwd=self.cwd) - stdout, stderr = p.communicate() - if DEBUG: - print stdout, stderr - return stdout, stderr - - -def _get_tmp_dir(): - return tempfile.mkdtemp(prefix='rc_integration_test') - - -def _construct_url(repo, dest=None, **kwargs): - if dest is None: - #make temp clone - dest = _get_tmp_dir() - params = { - 'user': TEST_USER_ADMIN_LOGIN, - 'passwd': TEST_USER_ADMIN_PASS, - 'host': HOST, - 'cloned_repo': repo, - 'dest': dest - } - params.update(**kwargs) - if params['user'] and params['passwd']: - _url = 'http://%(user)s:%(passwd)s@%(host)s/%(cloned_repo)s %(dest)s' % params - else: - _url = 'http://(host)s/%(cloned_repo)s %(dest)s' % params - return _url - - -def _add_files_and_push(vcs, DEST, **kwargs): - """ - Generate some files, add it to DEST repo and push back - vcs is git or hg and defines what VCS we want to make those files for - - :param vcs: - :param DEST: - """ - # commit some stuff into this repo - cwd = path = jn(DEST) - #added_file = jn(path, '%ssetupążźć.py' % _RandomNameSequence().next()) - added_file = jn(path, '%ssetup.py' % _RandomNameSequence().next()) - Command(cwd).execute('touch %s' % added_file) - Command(cwd).execute('%s add %s' % (vcs, added_file)) - - for i in xrange(kwargs.get('files_no', 3)): - cmd = """echo 'added_line%s' >> %s""" % (i, added_file) - Command(cwd).execute(cmd) - author_str = 'Marcin Kuźminski ' - if vcs == 'hg': - cmd = """hg commit -m 'commited new %s' -u '%s' %s """ % ( - i, author_str, added_file - ) - elif vcs == 'git': - cmd = """EMAIL="me@email.com" git commit -m 'commited new %s' --author '%s' %s """ % ( - i, author_str, added_file - ) - Command(cwd).execute(cmd) - - # PUSH it back - _REPO = None - if vcs == 'hg': - _REPO = HG_REPO - elif vcs == 'git': - _REPO = GIT_REPO - - kwargs['dest'] = '' - clone_url = _construct_url(_REPO, **kwargs) - if 'clone_url' in kwargs: - clone_url = kwargs['clone_url'] - stdout = stderr = None - if vcs == 'hg': - stdout, stderr = Command(cwd).execute('hg push --verbose', clone_url) - elif vcs == 'git': - stdout, stderr = Command(cwd).execute('git push --verbose', clone_url + " master") - - return stdout, stderr - - -def set_anonymous_access(enable=True): - user = User.get_by_username(User.DEFAULT_USER) - user.active = enable - Session().add(user) - Session().commit() - print '\tanonymous access is now:', enable - if enable != User.get_by_username(User.DEFAULT_USER).active: - raise Exception('Cannot set anonymous access') - - -#============================================================================== -# TESTS -#============================================================================== - - -def _check_proper_git_push(stdout, stderr): - #WTF Git stderr is output ?! - assert 'fatal' not in stderr - assert 'rejected' not in stderr - assert 'Pushing to' in stderr - assert 'master -> master' in stderr - - -class TestVCSOperations(BaseTestCase): - - @classmethod - def setup_class(cls): - #DISABLE ANONYMOUS ACCESS - set_anonymous_access(False) - - def setUp(self): - r = Repository.get_by_repo_name(GIT_REPO) - Repository.unlock(r) - r.enable_locking = False - Session().add(r) - Session().commit() - - r = Repository.get_by_repo_name(HG_REPO) - Repository.unlock(r) - r.enable_locking = False - Session().add(r) - Session().commit() - - def test_clone_hg_repo_by_admin(self): - clone_url = _construct_url(HG_REPO) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - - assert 'requesting all changes' in stdout - assert 'adding changesets' in stdout - assert 'adding manifests' in stdout - assert 'adding file changes' in stdout - - assert stderr == '' - - def test_clone_git_repo_by_admin(self): - clone_url = _construct_url(GIT_REPO) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - - assert 'Cloning into' in stdout - assert stderr == '' - - def test_clone_wrong_credentials_hg(self): - clone_url = _construct_url(HG_REPO, passwd='bad!') - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - assert 'abort: authorization failed' in stderr - - def test_clone_wrong_credentials_git(self): - clone_url = _construct_url(GIT_REPO, passwd='bad!') - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - assert 'fatal: Authentication failed' in stderr - - def test_clone_git_dir_as_hg(self): - clone_url = _construct_url(GIT_REPO) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - assert 'HTTP Error 404: Not Found' in stderr - - def test_clone_hg_repo_as_git(self): - clone_url = _construct_url(HG_REPO) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - assert 'not found' in stderr - - def test_clone_non_existing_path_hg(self): - clone_url = _construct_url('trololo') - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - assert 'HTTP Error 404: Not Found' in stderr - - def test_clone_non_existing_path_git(self): - clone_url = _construct_url('trololo') - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - assert 'not found' in stderr - - def test_push_new_file_hg(self): - DEST = _get_tmp_dir() - clone_url = _construct_url(HG_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - - stdout, stderr = _add_files_and_push('hg', DEST) - - assert 'pushing to' in stdout - assert 'Repository size' in stdout - assert 'Last revision is now' in stdout - - def test_push_new_file_git(self): - DEST = _get_tmp_dir() - clone_url = _construct_url(GIT_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - - # commit some stuff into this repo - stdout, stderr = _add_files_and_push('git', DEST) - - print [(x.repo_full_path,x.repo_path) for x in Repository.get_all()] - _check_proper_git_push(stdout, stderr) - - def test_push_invalidates_cache_hg(self): - key = CacheInvalidation.query().filter(CacheInvalidation.cache_key - ==HG_REPO).scalar() - if not key: - key = CacheInvalidation(HG_REPO, HG_REPO) - - key.cache_active = True - Session().add(key) - Session().commit() - - DEST = _get_tmp_dir() - clone_url = _construct_url(HG_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - - stdout, stderr = _add_files_and_push('hg', DEST, files_no=1) - - key = CacheInvalidation.query().filter(CacheInvalidation.cache_key - ==HG_REPO).one() - self.assertEqual(key.cache_active, False) - - def test_push_invalidates_cache_git(self): - key = CacheInvalidation.query().filter(CacheInvalidation.cache_key - ==GIT_REPO).scalar() - if not key: - key = CacheInvalidation(GIT_REPO, GIT_REPO) - - key.cache_active = True - Session().add(key) - Session().commit() - - DEST = _get_tmp_dir() - clone_url = _construct_url(GIT_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - - # commit some stuff into this repo - stdout, stderr = _add_files_and_push('git', DEST, files_no=1) - _check_proper_git_push(stdout, stderr) - - key = CacheInvalidation.query().filter(CacheInvalidation.cache_key - ==GIT_REPO).one() - print CacheInvalidation.get_all() - self.assertEqual(key.cache_active, False) - - def test_push_wrong_credentials_hg(self): - DEST = _get_tmp_dir() - clone_url = _construct_url(HG_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - - stdout, stderr = _add_files_and_push('hg', DEST, user='bad', - passwd='name') - - assert 'abort: authorization failed' in stderr - - def test_push_wrong_credentials_git(self): - DEST = _get_tmp_dir() - clone_url = _construct_url(GIT_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - - stdout, stderr = _add_files_and_push('git', DEST, user='bad', - passwd='name') - - assert 'fatal: Authentication failed' in stderr - - def test_push_back_to_wrong_url_hg(self): - DEST = _get_tmp_dir() - clone_url = _construct_url(HG_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - - stdout, stderr = _add_files_and_push('hg', DEST, - clone_url='http://127.0.0.1:5000/tmp',) - - assert 'HTTP Error 404: Not Found' in stderr - - def test_push_back_to_wrong_url_git(self): - DEST = _get_tmp_dir() - clone_url = _construct_url(GIT_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - - stdout, stderr = _add_files_and_push('git', DEST, - clone_url='http://127.0.0.1:5000/tmp',) - - assert 'not found' in stderr - - def test_clone_and_create_lock_hg(self): - # enable locking - r = Repository.get_by_repo_name(HG_REPO) - r.enable_locking = True - Session().add(r) - Session().commit() - # clone - clone_url = _construct_url(HG_REPO) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - - #check if lock was made - r = Repository.get_by_repo_name(HG_REPO) - assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id - - def test_clone_and_create_lock_git(self): - # enable locking - r = Repository.get_by_repo_name(GIT_REPO) - r.enable_locking = True - Session().add(r) - Session().commit() - # clone - clone_url = _construct_url(GIT_REPO) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - - #check if lock was made - r = Repository.get_by_repo_name(GIT_REPO) - assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id - - def test_clone_after_repo_was_locked_hg(self): - #lock repo - r = Repository.get_by_repo_name(HG_REPO) - Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) - #pull fails since repo is locked - clone_url = _construct_url(HG_REPO) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" - % (HG_REPO, TEST_USER_ADMIN_LOGIN)) - assert msg in stderr - - def test_clone_after_repo_was_locked_git(self): - #lock repo - r = Repository.get_by_repo_name(GIT_REPO) - Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) - #pull fails since repo is locked - clone_url = _construct_url(GIT_REPO) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - msg = ("""The requested URL returned error: 423""") - assert msg in stderr - - def test_push_on_locked_repo_by_other_user_hg(self): - #clone some temp - DEST = _get_tmp_dir() - clone_url = _construct_url(HG_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - - #lock repo - r = Repository.get_by_repo_name(HG_REPO) - # let this user actually push ! - RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, - perm='repository.write') - Session().commit() - Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) - - #push fails repo is locked by other user ! - stdout, stderr = _add_files_and_push('hg', DEST, - user=TEST_USER_REGULAR_LOGIN, - passwd=TEST_USER_REGULAR_PASS) - msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" - % (HG_REPO, TEST_USER_ADMIN_LOGIN)) - assert msg in stderr - - def test_push_on_locked_repo_by_other_user_git(self): - #clone some temp - DEST = _get_tmp_dir() - clone_url = _construct_url(GIT_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - - #lock repo - r = Repository.get_by_repo_name(GIT_REPO) - # let this user actually push ! - RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, - perm='repository.write') - Session().commit() - Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) - - #push fails repo is locked by other user ! - stdout, stderr = _add_files_and_push('git', DEST, - user=TEST_USER_REGULAR_LOGIN, - passwd=TEST_USER_REGULAR_PASS) - err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN) - assert err in stderr - - #TODO: fix this somehow later on Git, Git is stupid and even if we throw - #back 423 to it, it makes ANOTHER request and we fail there with 405 :/ - - msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" - % (GIT_REPO, TEST_USER_ADMIN_LOGIN)) - #msg = "405 Method Not Allowed" - #assert msg in stderr - - def test_push_unlocks_repository_hg(self): - # enable locking - r = Repository.get_by_repo_name(HG_REPO) - r.enable_locking = True - Session().add(r) - Session().commit() - #clone some temp - DEST = _get_tmp_dir() - clone_url = _construct_url(HG_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - - #check for lock repo after clone - r = Repository.get_by_repo_name(HG_REPO) - uid = User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id - assert r.locked[0] == uid - - #push is ok and repo is now unlocked - stdout, stderr = _add_files_and_push('hg', DEST) - assert ('remote: Released lock on repo `%s`' % HG_REPO) in stdout - #we need to cleanup the Session Here ! - Session.remove() - r = Repository.get_by_repo_name(HG_REPO) - assert r.locked == [None, None] - - #TODO: fix me ! somehow during tests hooks don't get called on Git - def test_push_unlocks_repository_git(self): - # enable locking - r = Repository.get_by_repo_name(GIT_REPO) - r.enable_locking = True - Session().add(r) - Session().commit() - #clone some temp - DEST = _get_tmp_dir() - clone_url = _construct_url(GIT_REPO, dest=DEST) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - - #check for lock repo after clone - r = Repository.get_by_repo_name(GIT_REPO) - assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id - - #push is ok and repo is now unlocked - stdout, stderr = _add_files_and_push('git', DEST) - _check_proper_git_push(stdout, stderr) - - #assert ('remote: Released lock on repo `%s`' % GIT_REPO) in stdout - #we need to cleanup the Session Here ! - Session.remove() - r = Repository.get_by_repo_name(GIT_REPO) - assert r.locked == [None, None] - - def test_ip_restriction_hg(self): - user_model = UserModel() - try: - user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') - Session().commit() - clone_url = _construct_url(HG_REPO) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - assert 'abort: HTTP Error 403: Forbidden' in stderr - finally: - #release IP restrictions - for ip in UserIpMap.getAll(): - UserIpMap.delete(ip.ip_id) - Session().commit() - - time.sleep(2) - clone_url = _construct_url(HG_REPO) - stdout, stderr = Command('/tmp').execute('hg clone', clone_url) - - assert 'requesting all changes' in stdout - assert 'adding changesets' in stdout - assert 'adding manifests' in stdout - assert 'adding file changes' in stdout - - assert stderr == '' - - def test_ip_restriction_git(self): - user_model = UserModel() - try: - user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') - Session().commit() - clone_url = _construct_url(GIT_REPO) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - msg = ("""The requested URL returned error: 403""") - assert msg in stderr - finally: - #release IP restrictions - for ip in UserIpMap.getAll(): - UserIpMap.delete(ip.ip_id) - Session().commit() - - time.sleep(2) - clone_url = _construct_url(GIT_REPO) - stdout, stderr = Command('/tmp').execute('git clone', clone_url) - - assert 'Cloning into' in stdout - assert stderr == '' diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/parameterized.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/tests/parameterized.py Thu May 07 16:24:29 2015 +0200 @@ -0,0 +1,241 @@ +import re +import new +import inspect +import logging +import logging.handlers +from functools import wraps + +from unittest import TestCase + + +def skip_test(func): + try: + from nose.tools import nottest + except ImportError: + pass + else: + func = nottest(func) + + try: + import pytest + except ImportError: + pass + else: + func = pytest.mark.skipIf(True, func) + + return func + + +def _terrible_magic_get_defining_classes(): + """ Returns the set of parent classes of the class currently being defined. + Will likely only work if called from the ``parameterized`` decorator. + This function is entirely @brandon_rhodes's fault, as he suggested + the implementation: http://stackoverflow.com/a/8793684/71522 + """ + stack = inspect.stack() + if len(stack) <= 4: + return [] + frame = stack[3] + code_context = frame[4][0].strip() + if not code_context.startswith("class "): + return [] + _, parents = code_context.split("(", 1) + parents, _ = parents.rsplit(")", 1) + return eval("[" + parents + "]", frame[0].f_globals, frame[0].f_locals) + + +def parameterized(input): + """ Parameterize a test case: + >>> add1_tests = [(1, 2), (2, 3)] + >>> class TestFoo(object): + ... @parameterized(add1_tests) + ... def test_add1(self, input, expected): + ... assert_equal(add1(input), expected) + >>> @parameterized(add1_tests) + ... def test_add1(input, expected): + ... assert_equal(add1(input), expected) + >>> + """ + + if not hasattr(input, "__iter__"): + raise ValueError("expected iterable input; got %r" % (input,)) + + def parameterized_helper(f): + attached_instance_method = [False] + + parent_classes = _terrible_magic_get_defining_classes() + if any(issubclass(cls, TestCase) for cls in parent_classes): + raise Exception("Warning: '@parameterized' tests won't work " + "inside subclasses of 'TestCase' - use " + "'@parameterized.expand' instead") + + @wraps(f) + def parameterized_helper_method(self=None): + if self is not None and not attached_instance_method[0]: + # confusingly, we need to create a named instance method and + # attach that to the class... + cls = self.__class__ + im_f = new.instancemethod(f, None, cls) + setattr(cls, f.__name__, im_f) + attached_instance_method[0] = True + for args in input: + if isinstance(args, basestring): + args = [args] + # ... then pull that named instance method off, turning it into + # a bound method ... + if self is not None: + args = [getattr(self, f.__name__)] + list(args) + else: + args = [f] + list(args) + # ... then yield that as a tuple. If those steps aren't + # followed precicely, Nose gets upset and doesn't run the test + # or doesn't run setup methods. + yield tuple(args) + + f.__name__ = "_helper_for_%s" % (f.__name__,) + parameterized_helper_method.parameterized_input = input + parameterized_helper_method.parameterized_func = f + return parameterized_helper_method + + return parameterized_helper + + +def to_safe_name(s): + return re.sub("[^a-zA-Z0-9_]", "", s) + + +def parameterized_expand_helper(func_name, func, args): + def parameterized_expand_helper_helper(self=()): + if self != (): + self = (self,) + return func(*(self + args)) + parameterized_expand_helper_helper.__name__ = str(func_name) + return parameterized_expand_helper_helper + + +def parameterized_expand(input): + """ A "brute force" method of parameterizing test cases. Creates new test + cases and injects them into the namespace that the wrapped function + is being defined in. Useful for parameterizing tests in subclasses + of 'UnitTest', where Nose test generators don't work. + + >>> @parameterized.expand([("foo", 1, 2)]) + ... def test_add1(name, input, expected): + ... actual = add1(input) + ... assert_equal(actual, expected) + ... + >>> locals() + ... 'test_add1_foo_0': ... + >>> + """ + + def parameterized_expand_wrapper(f): + stack = inspect.stack() + frame = stack[1] + frame_locals = frame[0].f_locals + + base_name = f.__name__ + for num, args in enumerate(input): + name_suffix = "_%s" % (num,) + if len(args) > 0 and isinstance(args[0], basestring): + name_suffix += "_" + to_safe_name(args[0]) + name = base_name + name_suffix + new_func = parameterized_expand_helper(name, f, args) + frame_locals[name] = new_func + return skip_test(f) + return parameterized_expand_wrapper + +parameterized.expand = parameterized_expand + + +def assert_contains(haystack, needle): + if needle not in haystack: + raise AssertionError("%r not in %r" % (needle, haystack)) + + +def assert_not_contains(haystack, needle): + if needle in haystack: + raise AssertionError("%r in %r" % (needle, haystack)) + + +def assert_raises(func, exc_type, str_contains=None, repr_contains=None): + try: + func() + except exc_type, e: + if str_contains is not None and str_contains not in str(e): + raise AssertionError("%s raised, but %r does not contain %r" + % (exc_type, str(e), str_contains)) + if repr_contains is not None and repr_contains not in repr(e): + raise AssertionError("%s raised, but %r does not contain %r" + % (exc_type, repr(e), repr_contains)) + return e + else: + raise AssertionError("%s not raised" % (exc_type,)) + + +log_handler = None + + +def setup_logging(): + """ Configures a log handler which will capure log messages during a test. + The ``logged_messages`` and ``assert_no_errors_logged`` functions can be + used to make assertions about these logged messages. + + For example:: + + from ensi_common.testing import ( + setup_logging, teardown_logging, assert_no_errors_logged, + assert_logged, + ) + + class TestWidget(object): + def setup(self): + setup_logging() + + def teardown(self): + assert_no_errors_logged() + teardown_logging() + + def test_that_will_fail(self): + log.warning("this warning message will trigger a failure") + + def test_that_will_pass(self): + log.info("but info messages are ok") + assert_logged("info messages are ok") + """ + + global log_handler + if log_handler is not None: + logging.getLogger().removeHandler(log_handler) + log_handler = logging.handlers.BufferingHandler(1000) + formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s") + log_handler.setFormatter(formatter) + logging.getLogger().addHandler(log_handler) + + +def teardown_logging(): + global log_handler + if log_handler is not None: + logging.getLogger().removeHandler(log_handler) + log_handler = None + + +def logged_messages(): + assert log_handler, "setup_logging not called" + return [(log_handler.format(record), record) for record in log_handler.buffer] + + +def assert_no_errors_logged(): + for _, record in logged_messages(): + if record.levelno >= logging.WARNING: + # Assume that the nose log capture plugin is being used, so it will + # show the exception. + raise AssertionError("an unexpected error was logged") + + +def assert_logged(expected_msg_contents): + for msg, _ in logged_messages(): + if expected_msg_contents in msg: + return + raise AssertionError("no logged message contains %r" + % (expected_msg_contents,)) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/scripts/create_rc.sh --- a/kallithea/tests/scripts/create_rc.sh Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/scripts/create_rc.sh Thu May 07 16:24:29 2015 +0200 @@ -1,10 +1,10 @@ #!/bin/sh psql -U postgres -h localhost -c 'drop database if exists kallithea;' psql -U postgres -h localhost -c 'create database kallithea;' -paster setup-db rc.ini --force-yes --user=username --password=qweqwe --email=username@example.com --repos=/home/username/repos --no-public-access +paster setup-db server.ini --force-yes --user=username --password=qweqwe --email=username@example.com --repos=/home/username/repos --no-public-access API_KEY=`psql -R " " -A -U postgres -h localhost -c "select api_key from users where admin=TRUE" -d kallithea | awk '{print $2}'` echo "run those after running server" -paster serve rc.ini --pid-file=rc.pid --daemon +paster serve server.ini --pid-file=server.pid --daemon sleep 3 kallithea-api --apikey=$API_KEY --apihost=http://127.0.0.1:5001 create_user username:demo1 password:qweqwe email:demo1@example.com kallithea-api --apikey=$API_KEY --apihost=http://127.0.0.1:5001 create_user username:demo2 password:qweqwe email:demo2@example.com @@ -13,5 +13,5 @@ kallithea-api --apikey=$API_KEY --apihost=http://127.0.0.1:5001 add_user_to_user_group usergroupid:demo12 userid:demo1 kallithea-api --apikey=$API_KEY --apihost=http://127.0.0.1:5001 add_user_to_user_group usergroupid:demo12 userid:demo2 echo "killing server" -kill `cat rc.pid` -rm rc.pid +kill `cat server.pid` +rm server.pid diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/scripts/test_concurency.py --- a/kallithea/tests/scripts/test_concurency.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/scripts/test_concurency.py Thu May 07 16:24:29 2015 +0200 @@ -49,14 +49,14 @@ from kallithea.config.environment import load_environment rel_path = dn(dn(dn(dn(os.path.abspath(__file__))))) -conf = appconfig('config:rc.ini', relative_to=rel_path) +conf = appconfig('config:development.ini', relative_to=rel_path) load_environment(conf.global_conf, conf.local_conf) add_cache(conf) USER = 'test_admin' PASS = 'test12' -HOST = 'rc.local' +HOST = 'server.local' METHOD = 'pull' DEBUG = True log = logging.getLogger(__name__) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/scripts/test_crawler.py --- a/kallithea/tests/scripts/test_crawler.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/scripts/test_crawler.py Thu May 07 16:24:29 2015 +0200 @@ -60,7 +60,7 @@ print 'Crawling @ %s' % BASE_URI BASE_URI += '%s' -PROJECT_PATH = jn('/', 'home', 'marcink', 'repos') +PROJECT_PATH = jn('/', 'home', 'username', 'repos') PROJECTS = [ #'linux-magx-pbranch', 'CPython', diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/base.py --- a/kallithea/tests/vcs/base.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/base.py Thu May 07 16:24:29 2015 +0200 @@ -13,7 +13,7 @@ from kallithea.lib.vcs.nodes import FileNode -class BackendTestMixin(object): +class _BackendTestMixin(object): """ This is a backend independent test case class which should be created with ``type`` method. @@ -103,7 +103,7 @@ 'backend_alias': alias, } cls_name = ''.join(('%s base backend test' % alias).title().split()) - bases = (BackendTestMixin, unittest.TestCase) + bases = (_BackendTestMixin, unittest.TestCase) globals()[cls_name] = type(cls_name, bases, attrs) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/test_archives.py --- a/kallithea/tests/vcs/test_archives.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/test_archives.py Thu May 07 16:24:29 2015 +0200 @@ -6,14 +6,14 @@ import datetime import tempfile import StringIO -from kallithea.tests.vcs.base import BackendTestMixin +from kallithea.tests.vcs.base import _BackendTestMixin from kallithea.tests.vcs.conf import SCM_TESTS from kallithea.lib.vcs.exceptions import VCSError from kallithea.lib.vcs.nodes import FileNode from kallithea.lib.vcs.utils.compat import unittest -class ArchivesTestCaseMixin(BackendTestMixin): +class ArchivesTestCaseMixin(_BackendTestMixin): @classmethod def _get_commits(cls): diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/test_branches.py --- a/kallithea/tests/vcs/test_branches.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/test_branches.py Thu May 07 16:24:29 2015 +0200 @@ -5,11 +5,11 @@ from kallithea.lib.vcs.utils.compat import unittest from kallithea.lib.vcs.nodes import FileNode -from kallithea.tests.vcs.base import BackendTestMixin +from kallithea.tests.vcs.base import _BackendTestMixin from kallithea.tests.vcs.conf import SCM_TESTS -class BranchesTestCaseMixin(BackendTestMixin): +class BranchesTestCaseMixin(_BackendTestMixin): @classmethod def _get_commits(cls): diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/test_changesets.py --- a/kallithea/tests/vcs/test_changesets.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/test_changesets.py Thu May 07 16:24:29 2015 +0200 @@ -4,7 +4,7 @@ import time import datetime from kallithea.lib import vcs -from kallithea.tests.vcs.base import BackendTestMixin +from kallithea.tests.vcs.base import _BackendTestMixin from kallithea.tests.vcs.conf import SCM_TESTS from kallithea.lib.vcs.backends.base import BaseChangeset @@ -50,7 +50,7 @@ 'removed': [], }) -class ChangesetsWithCommitsTestCaseixin(BackendTestMixin): +class _ChangesetsWithCommitsTestCaseixin(_BackendTestMixin): recreate_repo_per_test = True @classmethod @@ -146,7 +146,7 @@ self.assertEqual([sha], self.repo.get_changeset(test_rev).children) -class ChangesetsTestCaseMixin(BackendTestMixin): +class _ChangesetsTestCaseMixin(_BackendTestMixin): recreate_repo_per_test = False @classmethod @@ -301,7 +301,7 @@ list(self.repo.get_changesets(start=last-1, end=0)) -class ChangesetsChangesTestCaseMixin(BackendTestMixin): +class _ChangesetsChangesTestCaseMixin(_BackendTestMixin): recreate_repo_per_test = False @classmethod @@ -373,17 +373,17 @@ } # tests with additional commits cls_name = ''.join(('%s changesets with commits test' % alias).title().split()) - bases = (ChangesetsWithCommitsTestCaseixin, unittest.TestCase) + bases = (_ChangesetsWithCommitsTestCaseixin, unittest.TestCase) globals()[cls_name] = type(cls_name, bases, attrs) # tests without additional commits cls_name = ''.join(('%s changesets test' % alias).title().split()) - bases = (ChangesetsTestCaseMixin, unittest.TestCase) + bases = (_ChangesetsTestCaseMixin, unittest.TestCase) globals()[cls_name] = type(cls_name, bases, attrs) # tests changes cls_name = ''.join(('%s changesets changes test' % alias).title().split()) - bases = (ChangesetsChangesTestCaseMixin, unittest.TestCase) + bases = (_ChangesetsChangesTestCaseMixin, unittest.TestCase) globals()[cls_name] = type(cls_name, bases, attrs) diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/test_getitem.py --- a/kallithea/tests/vcs/test_getitem.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/test_getitem.py Thu May 07 16:24:29 2015 +0200 @@ -1,13 +1,13 @@ from __future__ import with_statement import datetime -from kallithea.tests.vcs.base import BackendTestMixin +from kallithea.tests.vcs.base import _BackendTestMixin from kallithea.tests.vcs.conf import SCM_TESTS from kallithea.lib.vcs.nodes import FileNode from kallithea.lib.vcs.utils.compat import unittest -class GetitemTestCaseMixin(BackendTestMixin): +class GetitemTestCaseMixin(_BackendTestMixin): @classmethod def _get_commits(cls): diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/test_getslice.py --- a/kallithea/tests/vcs/test_getslice.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/test_getslice.py Thu May 07 16:24:29 2015 +0200 @@ -1,13 +1,13 @@ from __future__ import with_statement import datetime -from kallithea.tests.vcs.base import BackendTestMixin +from kallithea.tests.vcs.base import _BackendTestMixin from kallithea.tests.vcs.conf import SCM_TESTS from kallithea.lib.vcs.nodes import FileNode from kallithea.lib.vcs.utils.compat import unittest -class GetsliceTestCaseMixin(BackendTestMixin): +class GetsliceTestCaseMixin(_BackendTestMixin): @classmethod def _get_commits(cls): diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/test_git.py --- a/kallithea/tests/vcs/test_git.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/test_git.py Thu May 07 16:24:29 2015 +0200 @@ -8,7 +8,7 @@ from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState from kallithea.lib.vcs.utils.compat import unittest -from kallithea.tests.vcs.base import BackendTestMixin +from kallithea.tests.vcs.base import _BackendTestMixin from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, get_new_dir @@ -620,7 +620,7 @@ changeset.added -class GitSpecificWithRepoTest(BackendTestMixin, unittest.TestCase): +class GitSpecificWithRepoTest(_BackendTestMixin, unittest.TestCase): backend_alias = 'git' @classmethod @@ -688,7 +688,7 @@ % (3, self.repo._get_revision(0), self.repo._get_revision(1))) -class GitRegressionTest(BackendTestMixin, unittest.TestCase): +class GitRegressionTest(_BackendTestMixin, unittest.TestCase): backend_alias = 'git' @classmethod diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/test_repository.py --- a/kallithea/tests/vcs/test_repository.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/test_repository.py Thu May 07 16:24:29 2015 +0200 @@ -1,6 +1,6 @@ from __future__ import with_statement import datetime -from kallithea.tests.vcs.base import BackendTestMixin +from kallithea.tests.vcs.base import _BackendTestMixin from kallithea.tests.vcs.conf import SCM_TESTS from kallithea.tests.vcs.conf import TEST_USER_CONFIG_FILE from kallithea.lib.vcs.nodes import FileNode @@ -8,7 +8,7 @@ from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError -class RepositoryBaseTest(BackendTestMixin): +class RepositoryBaseTest(_BackendTestMixin): recreate_repo_per_test = False @classmethod @@ -46,7 +46,7 @@ self.assertTrue(self.repo != dummy()) -class RepositoryGetDiffTest(BackendTestMixin): +class RepositoryGetDiffTest(_BackendTestMixin): @classmethod def _get_commits(cls): diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/test_tags.py --- a/kallithea/tests/vcs/test_tags.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/test_tags.py Thu May 07 16:24:29 2015 +0200 @@ -1,13 +1,13 @@ from __future__ import with_statement -from kallithea.tests.vcs.base import BackendTestMixin +from kallithea.tests.vcs.base import _BackendTestMixin from kallithea.tests.vcs.conf import SCM_TESTS from kallithea.lib.vcs.exceptions import TagAlreadyExistError from kallithea.lib.vcs.exceptions import TagDoesNotExistError from kallithea.lib.vcs.utils.compat import unittest -class TagsTestCaseMixin(BackendTestMixin): +class TagsTestCaseMixin(_BackendTestMixin): def test_new_tag(self): tip = self.repo.get_changeset() diff -r a9d2e2958514 -r 7117a83b4b3a kallithea/tests/vcs/test_utils.py --- a/kallithea/tests/vcs/test_utils.py Thu May 07 16:23:45 2015 +0200 +++ b/kallithea/tests/vcs/test_utils.py Thu May 07 16:24:29 2015 +0200 @@ -185,14 +185,14 @@ class TestAuthorExtractors(unittest.TestCase): - TEST_AUTHORS = [('Marcin Kuzminski ', - ('Marcin Kuzminski', 'marcin@python-works.com')), - ('Marcin Kuzminski Spaces < marcin@python-works.com >', - ('Marcin Kuzminski Spaces', 'marcin@python-works.com')), - ('Marcin Kuzminski ', - ('Marcin Kuzminski', 'marcin.kuzminski@python-works.com')), - ('mrf RFC_SPEC ', - ('mrf RFC_SPEC', 'marcin+kuzminski@python-works.com')), + TEST_AUTHORS = [("Username Last'o'Name ", + ("Username Last'o'Name", "username@python-works.com")), + ("Username Last'o'Name Spaces < username@python-works.com >", + ("Username Last'o'Name Spaces", "username@python-works.com")), + ("Username Last'o'Name ", + ("Username Last'o'Name", "username.lastname@python-works.com")), + ('mrf RFC_SPEC ', + ('mrf RFC_SPEC', 'username+lastname@python-works.com')), ('username ', ('username', 'user@email.com')), ('username diff -r a9d2e2958514 -r 7117a83b4b3a setup.cfg --- a/setup.cfg Thu May 07 16:23:45 2015 +0200 +++ b/setup.cfg Thu May 07 16:24:29 2015 +0200 @@ -10,6 +10,9 @@ detailed-errors = 1 nologcapture = 1 +[pytest] +norecursedirs = .* *.egg kallithea/tests/scripts + [compile_catalog] domain = kallithea directory = kallithea/i18n diff -r a9d2e2958514 -r 7117a83b4b3a test.ini --- a/test.ini Thu May 07 16:23:45 2015 +0200 +++ b/test.ini Thu May 07 16:24:29 2015 +0200 @@ -133,7 +133,7 @@ host = 127.0.0.1 port = 5000 -## prefix middleware for rc +## middleware for hosting the WSGI application under a URL prefix #[filter:proxy-prefix] #use = egg:PasteDeploy#prefix #prefix = / diff -r a9d2e2958514 -r 7117a83b4b3a tox.ini --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tox.ini Thu May 07 16:24:29 2015 +0200 @@ -0,0 +1,12 @@ +[tox] +envlist = py{26,27}-{pytest,nose} + +[testenv] +setenv = + PYTHONHASHSEED = 0 +deps = + nose: nose + pytest: pytest +commands = + nose: nosetests {posargs} + pytest: py.test {posargs}